How to send email from custom hook?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • rautekuvchvat
    Junior Member
    • Jan 2023
    • 6

    How to send email from custom hook?

    Hello,

    I want to send email from custom hook, I wasnt able to find it or make it using \Espo\Services\Email. Thank you.
  • rabii
    Active Community Member
    • Jun 2016
    • 1263

    #2
    Hey try this code below, i have not tested the code but i think it will work.

    PHP Code:
    <?php
    namespace Espo\Custom\Hooks\YourEntity;
    
    use Espo\Core\ORM\Repository\Option\SaveOption;
    use Espo\Core\Utils\SystemUser;
    use Espo\Core\InjectableFactory;
    use Espo\Core\ServiceFactory;
    use Espo\ORM\EntityManager;
    use Espo\Entities\Email;
    use Espo\Tools\Email\SendService;
    
    class SendEmail
    {
        public static $order = 1;
    
        public function __construct(
            private EntityManager $entityManager,
            private ServiceFactory $serviceFactory,
            private InjectableFactory $injectableFactory,
        ){}
    
        public function beforeSave(Entity $entity, array $options): void
        {
            if (!empty($options[SaveOption::SILENT])) {
                return;
            }
    
            $em = $this->entityManager;
    
            $id = $em->createEntity(Email::ENTITY_TYPE, [
                'from', 'from-address@test.com',
                'to', 'to-address@test.com',
                'subject', 'Test from hooks',
                'body', 'Hi,\n\nThis is a your email body.',
                'isHtml', true
            ]);
    
            /** @var ?Email $email */
            $email = $this->entityManager->getEntityById(Email::ENTITY_TYPE, $id);
    
            if (!$email) {
                $this->log("Email '{$id}' does not exist.");
                return;
            }
    
            $status = $email->getStatus();
    
            if ($status === Email::STATUS_SENT) {
                $this->log("Can't send email that has 'Sent' status.");
                return;
            }
    
            /** @var \Espo\Services\Email $service */
            $service = $this->serviceFactory->create(Email::ENTITY_TYPE);
    
            $service->loadAdditionalFields($email);
    
            $toSave = false;
    
            if ($status !== Email::STATUS_SENDING) {
                $email->set('status', Email::STATUS_SENDING);
                $toSave = true;
            }
    
            $systemUserId = $this->injectableFactory->create(SystemUser::class)->getId();
    
            if ($toSave) {
                $em->saveEntity($email, [
                    SaveOption::SILENT => true,
                    SaveOption::MODIFIED_BY_ID => $systemUserId,
                ]);
            }
    
           $sendService = $this->injectableFactory->create(SendService::class);
    
           try {
                $sendService->send($email);
            }
            catch (Exception $e) {
                $message = $e->getMessage();
                $this->log("Error while sending. Message: {$message}." , 'error');
            }
        }
    }
    Rabii
    Web Dev

    Comment

    • rautekuvchvat
      Junior Member
      • Jan 2023
      • 6

      #3
      Hey rabii, thank you for your effort! Unfortunately, this code doesnt work for me, I tried to go through whats wrong, but I didnt manage to repair it. I added below some of the errors it gave me after I used your code and tried to modify it.
      Click image for larger version

Name:	image.png
Views:	272
Size:	104.8 KB
ID:	89879​​
      Attached Files

      Comment

      • rabii
        Active Community Member
        • Jun 2016
        • 1263

        #4
        Try this i have made some changes, if it doesn't work send me the log file as a text, the picture you have attached is not showing all the errors properly.

        PHP Code:
        <?php
        namespace Espo\Custom\Hooks\Holiday;
        
        use Espo\Core\ORM\Repository\Option\SaveOption;
        use Espo\Core\Utils\SystemUser;
        use Espo\Core\InjectableFactory;
        use Espo\Core\ServiceFactory;
        use Espo\ORM\EntityManager;
        use Espo\ORM\Entity;
        use Espo\Entities\Email;
        use Espo\Tools\Email\SendService;
        
        class SendEmail
        {
            public static $order = 1;
        
            public function __construct(
                private EntityManager $entityManager,
                private ServiceFactory $serviceFactory,
                private InjectableFactory $injectableFactory,
            ){}
        
            public function beforeSave(Entity $entity, array $options): void
            {
                if (!empty($options[SaveOption::SILENT])) {
                    return;
                }
        
              $em = $this->entityManager;
        
               $createdEmail = $em->createEntity(Email::ENTITY_TYPE, [
                    'from', 'from-address@test.com',
                    'to', 'to-address@test.com',
                    'subject', 'Test from hooks',
                    'body', 'Hi,\n\nThis is a your email body.',
                    'isHtml', true
                ]);
        
                /** @var ?Email $email */
                $email = $em->getEntityById(Email::ENTITY_TYPE, $createdEmail->getId());
        
                if (!$email) {
                    $this->log("Email '{$id}' does not exist.");
                    return;
                }
        
               $status = $email->getStatus();
        
                if ($status === Email::STATUS_SENT) {
                    $this->log("Can't send email that has 'Sent' status.");
                    return;
                }
        
                /** @var \Espo\Services\Email $service */
                $service = $this->serviceFactory->create(Email::ENTITY_TYPE);
        
                $service->loadAdditionalFields($email);
        
                $toSave = false;
        
               if ($status !== Email::STATUS_SENDING) {
                    $email->set('status', Email::STATUS_SENDING);
                    $toSave = true;
                }
        
                // if from email is not set use default system outbound
                if (!$email->get('from')) {
                    $from = $this->config->get('outboundEmailFromAddress');
                    if ($from) {
                        $email->set('from', $from);
                        $toSave = true;
                    }
                }
        
               $systemUserId = $this->injectableFactory->create(SystemUser::class)->getId();
        
               if ($toSave) {
                    $em->saveEntity($email, [
                        SaveOption::SILENT => true,
                        SaveOption::MODIFIED_BY_ID => $systemUserId,
                    ]);
                }
        
               $sendService = $this->injectableFactory->create(SendService::class);
        
               try {
                    $sendService->send($email);
                }
                catch (Exception $e) {
                    $message = $e->getMessage();
                    $this->log("Error while sending. Message: {$message}." , 'error');
                }
            }
        }
        Rabii
        Web Dev

        Comment

        • yuri
          Member
          • Mar 2014
          • 8624

          #5
          No need to use the service class. Just use Espo\Core\Mail\EmailSender (passed via constructor). An email entity can be created by Espo\Core\Mail\EmailFactory.
          If you find EspoCRM good, we would greatly appreciate if you could give the project a star on GitHub. We believe our work truly deserves more recognition. Thanks.

          Comment

          • rabii
            Active Community Member
            • Jun 2016
            • 1263

            #6
            Hey Yuri,

            if an email entity could be created through the email Factory like
            PHP Code:
            $createdEmail = $this->emailFactory->create(); 
            
            then how to set the attribute of the email entity. is the code below is correct then ? i have passed both EmailSender and EmailFactory through constructor and used them as below to create and send email.
            PHP Code:
            public function beforeSave(Entity $entity, array $options): void
                {
                    if (!empty($options[SaveOption::SILENT])) {
                        return;
                    }
                    $em = $this->entityManager;
                    $createdEmail = $this->emailFactory->create();
                    /** @var ?Email $email */
                    $email = $em->getEntityById(Email::ENTITY_TYPE, $createdEmail->getId());
                    if (!$email) {
                        $this->log("Email '{$id}' does not exist.");
                        return;
                    }
                    $status = $email->getStatus();
                    if ($status === Email::STATUS_SENT) {
                        $this->log("Can't send email that has 'Sent' status.");
                        return;
                    }
                    $toSave = false;
                    if ($status !== Email::STATUS_SENDING) {
                        $email->set('status', Email::STATUS_SENDING);
                        $toSave = true;
                    }
                    // if from email is not set use default system outbound
                    if (!$email->get('from')) {
                        $from = $this->config->get('outboundEmailFromAddress');
                        if ($from) {
                            $email->set('from', $from);
                            $toSave = true;
                        }
                    }
                    $systemUserId = $this->injectableFactory->create(SystemUser::class)->getId();
                    if ($toSave) {
                        $em->saveEntity($email, [
                            SaveOption::SILENT => true,
                            SaveOption::MODIFIED_BY_ID => $systemUserId,
                        ]);
                    }
                    try {
                        $this->emailSender->send($email);
                    }
                    catch (Exception $e) {
                        $message = $e->getMessage();
                        $this->log("Error while sending. Message: {$message}." , 'error');
                    }
                }
            Rabii
            Web Dev

            Comment

          Working...