How to send email from custom hook?

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

    #1

    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
    • 1395

    #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
    EspoCRM Custom Development

    🔗 Portfolio & Builds

    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:	424
Size:	104.8 KB
ID:	89879​​
      Attached Files

      Comment

      • rabii
        Active Community Member
        • Jun 2016
        • 1395

        #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
        EspoCRM Custom Development

        🔗 Portfolio & Builds

        Comment

        • yuri
          EspoCRM product developer
          • Mar 2014
          • 9802

          #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.

          Comment

          • rabii
            Active Community Member
            • Jun 2016
            • 1395

            #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
            EspoCRM Custom Development

            🔗 Portfolio & Builds

            Comment

          Working...