Beispiel #1
0
 /**
  * Send an email to lead(s)
  *
  * @param       $email
  * @param       $leads
  * @param       $options = array()
  *     array source array('model', 'id')
  *     array emailSettings
  *     int   listId
  *     bool  allowResends     If false, exact emails (by id) already sent to the lead will not be resent
  *     bool  ignoreDNC        If true, emails listed in the do not contact table will still get the email
  *     bool  sendBatchMail    If false, the function will not send batched mail but will defer to calling function to handle it
  *     array assetAttachments Array of optional Asset IDs to attach
  *
  * @return mixed
  * @throws \Doctrine\ORM\ORMException
  */
 public function sendEmail($email, $leads, $options = array())
 {
     $source = isset($options['source']) ? $options['source'] : null;
     $emailSettings = isset($options['emailSettings']) ? $options['emailSettings'] : array();
     $listId = isset($options['listId']) ? $options['listId'] : null;
     $ignoreDNC = isset($options['ignoreDNC']) ? $options['ignoreDNC'] : false;
     $allowResends = isset($options['allowResends']) ? $options['allowResends'] : true;
     $tokens = isset($options['tokens']) ? $options['tokens'] : array();
     $sendBatchMail = isset($options['sendBatchMail']) ? $options['sendBatchMail'] : true;
     $assetAttachments = isset($options['assetAttachments']) ? $options['assetAttachments'] : array();
     $customHeaders = isset($options['customHeaders']) ? $options['customHeaders'] : array();
     if (!$email->getId()) {
         return false;
     }
     $singleEmail = false;
     if (isset($leads['id'])) {
         $singleEmail = true;
         $leads = array($leads['id'] => $leads);
     }
     /** @var \Mautic\EmailBundle\Entity\StatRepository $statRepo */
     $statRepo = $this->em->getRepository('MauticEmailBundle:Stat');
     /** @var \Mautic\EmailBundle\Entity\EmailRepository $emailRepo */
     $emailRepo = $this->getRepository();
     if (empty($emailSettings)) {
         //get email settings such as templates, weights, etc
         $emailSettings = $this->getEmailSettings($email);
     }
     if (!$allowResends) {
         static $sent = array();
         if (!isset($sent[$email->getId()])) {
             $sent[$email->getId()] = $statRepo->getSentStats($email->getId(), $listId);
         }
         $sendTo = array_diff_key($leads, $sent[$email->getId()]);
     } else {
         $sendTo = $leads;
     }
     if (!$ignoreDNC) {
         //get the list of do not contacts
         static $dnc;
         if (!is_array($dnc)) {
             $dnc = $emailRepo->getDoNotEmailList();
         }
         //weed out do not contacts
         if (!empty($dnc)) {
             foreach ($sendTo as $k => $lead) {
                 if (in_array(strtolower($lead['email']), $dnc)) {
                     unset($sendTo[$k]);
                 }
             }
         }
     }
     //get a count of leads
     $count = count($sendTo);
     //noone to send to so bail
     if (empty($count)) {
         return $singleEmail ? true : array();
     }
     //how many of this batch should go to which email
     $batchCount = 0;
     $backup = reset($emailSettings);
     foreach ($emailSettings as $eid => &$details) {
         if (isset($details['weight'])) {
             $limit = round($count * $details['weight']);
             if (!$limit) {
                 // Don't send any emails to this one
                 unset($emailSettings[$eid]);
             } else {
                 $details['limit'] = $limit;
             }
         } else {
             $details['limit'] = $count;
         }
     }
     if (count($emailSettings) == 0) {
         // Shouldn't happen but a safety catch
         $emailSettings[$backup['entity']->getId()] = $backup;
     }
     //randomize the leads for statistic purposes
     shuffle($sendTo);
     //start at the beginning for this batch
     $useEmail = reset($emailSettings);
     $errors = array();
     // Store stat entities
     $saveEntities = array();
     $mailer = $this->factory->getMailer(!$sendBatchMail);
     $contentGenerated = false;
     $flushQueue = function ($reset = true) use(&$mailer, &$saveEntities, &$errors, $sendBatchMail) {
         if ($sendBatchMail) {
             $flushResult = $mailer->flushQueue();
             if (!$flushResult) {
                 $sendFailures = $mailer->getErrors();
                 // Check to see if failed recipients were stored by the transport
                 if (!empty($sendFailures['failures'])) {
                     // Prevent the stat from saving
                     foreach ($sendFailures['failures'] as $failedEmail) {
                         // Add lead ID to list of failures
                         $errors[$saveEntities[$failedEmail]->getLead()->getId()] = $failedEmail;
                         // Down sent counts
                         $saveEntities[$failedEmail]->getEmail()->downSentCounts();
                         // Delete the stat
                         unset($saveEntities[$failedEmail]);
                     }
                 }
             }
             if ($reset) {
                 $mailer->reset(true);
             }
             return $flushResult;
         }
         return true;
     };
     foreach ($sendTo as $lead) {
         // Generate content
         if ($useEmail['entity']->getId() !== $contentGenerated) {
             // Flush the mail queue if applicable
             $flushQueue();
             $contentGenerated = $useEmail['entity']->getId();
             // Use batching/tokenization if supported
             $mailer->useMailerTokenization();
             $mailer->setSource($source);
             $mailer->setEmail($useEmail['entity'], true, $useEmail['slots'], $assetAttachments);
             if (!empty($customHeaders)) {
                 $mailer->setCustomHeaders($customHeaders);
             }
         }
         $idHash = uniqid();
         // Add tracking pixel token
         if (!empty($tokens)) {
             $mailer->setTokens($tokens);
         }
         $mailer->setLead($lead);
         $mailer->setIdHash($idHash);
         try {
             if (!$mailer->addTo($lead['email'], $lead['firstname'] . ' ' . $lead['lastname'])) {
                 // Clear the errors so it doesn't stop the next send
                 $mailer->clearErrors();
                 // Bad email so note and continue
                 $errors[$lead['id']] = $lead['email'];
                 continue;
             }
         } catch (BatchQueueMaxException $e) {
             // Queue full so flush then try again
             $flushQueue(false);
             $mailer->addTo($lead['email'], $lead['firstname'] . ' ' . $lead['lastname']);
         }
         //queue or send the message
         if (!$mailer->queue(true)) {
             $errors[$lead['id']] = $lead['email'];
             continue;
         }
         if (!$allowResends) {
             $sent[$useEmail['entity']->getId()][$lead['id']] = $lead['id'];
         }
         //create a stat
         $stat = new Stat();
         $stat->setDateSent(new \DateTime());
         $stat->setEmail($useEmail['entity']);
         $stat->setLead($this->em->getReference('MauticLeadBundle:Lead', $lead['id']));
         if ($listId) {
             $stat->setList($this->em->getReference('MauticLeadBundle:LeadList', $listId));
         }
         $stat->setEmailAddress($lead['email']);
         $stat->setTrackingHash($idHash);
         if (!empty($source)) {
             $stat->setSource($source[0]);
             $stat->setSourceId($source[1]);
         }
         $stat->setCopy($mailer->getBody());
         $stat->setTokens($mailer->getTokens());
         $saveEntities[$lead['email']] = $stat;
         // Down sent counts
         $saveEntities[$lead['email']]->getEmail()->upSentCounts();
         // Save RAM
         unset($stat);
         $batchCount++;
         if ($batchCount >= $useEmail['limit']) {
             unset($useEmail);
             //use the next email
             $batchCount = 0;
             $useEmail = next($emailSettings);
         }
     }
     // Send batched mail if applicable
     $flushQueue();
     // Persist stats
     $statRepo->saveEntities($saveEntities);
     // Free RAM
     foreach ($saveEntities as $stat) {
         $this->em->detach($stat);
         unset($stat);
     }
     unset($emailSettings, $options, $tokens, $useEmail, $sendTo);
     return $singleEmail ? empty($errors) : $errors;
 }
Beispiel #2
0
 /**
  * Create an email stat
  *
  * @param bool|true   $persist
  * @param string|null $emailAddress
  * @param null        $listId
  *
  * @return Stat|void
  * @throws \Doctrine\ORM\ORMException
  */
 public function createEmailStat($persist = true, $emailAddress = null, $listId = null)
 {
     static $copies = array();
     //create a stat
     $stat = new Stat();
     $stat->setDateSent(new \DateTime());
     $stat->setEmail($this->email);
     // Note if a lead
     if (null !== $this->lead) {
         $stat->setLead($this->factory->getEntityManager()->getReference('MauticLeadBundle:Lead', $this->lead['id']));
         $emailAddress = $this->lead['email'];
     }
     // Find email if applicable
     if (null === $emailAddress) {
         // Use the last address set
         $emailAddresses = $this->message->getTo();
         if (count($emailAddresses)) {
             end($emailAddresses);
             $emailAddress = key($emailAddresses);
         }
     }
     $stat->setEmailAddress($emailAddress);
     // Note if sent from a lead list
     if (null !== $listId) {
         $stat->setList($this->factory->getEntityManager()->getReference('MauticLeadBundle:LeadList', $listId));
     }
     $stat->setTrackingHash($this->idHash);
     if (!empty($this->source)) {
         $stat->setSource($this->source[0]);
         $stat->setSourceId($this->source[1]);
     }
     $stat->setTokens($this->getTokens());
     /** @var \Mautic\EmailBundle\Model\EmailModel $emailModel */
     $emailModel = $this->factory->getModel('email');
     // Save a copy of the email - use email ID if available simply to prevent from having to rehash over and over
     $id = null !== $this->email ? $this->email->getId() : md5($this->subject . $this->body['content']);
     if (!isset($copies[$id])) {
         $hash = strlen($id) !== 32 ? md5($this->subject . $this->body['content']) : $id;
         $copy = $emailModel->getCopyRepository()->findByHash($hash);
         if (null === $copy) {
             // Create a copy entry
             $copy = new Copy();
             $copy->setId($hash)->setBody($this->body['content'])->setSubject($this->subject)->setDateCreated(new \DateTime())->setEmail($this->email);
             $emailModel->getCopyRepository()->saveEntity($copy);
         }
         $copies[$id] = $copy;
     }
     $stat->setStoredCopy($copies[$id]);
     if ($persist) {
         $emailModel->getStatRepository()->saveEntity($stat);
     }
     return $stat;
 }
Beispiel #3
0
 /**
  * Test that processMailerCallback handles an array of hashIds correctly.
  */
 public function testProcessMailerCallbackWithHashIds()
 {
     // Setup dependencies
     $ipLookupHelper = $this->getMockBuilder(IpLookupHelper::class)->disableOriginalConstructor()->getMock();
     $themeHelper = $this->getMockBuilder(ThemeHelper::class)->disableOriginalConstructor()->getMock();
     $mailboxHelper = $this->getMockBuilder(Mailbox::class)->disableOriginalConstructor()->getMock();
     $mailHelper = $this->getMockBuilder(MailHelper::class)->disableOriginalConstructor()->getMock();
     $leadModel = $this->getMockBuilder(LeadModel::class)->disableOriginalConstructor()->getMock();
     $trackableModel = $this->getMockBuilder(TrackableModel::class)->disableOriginalConstructor()->getMock();
     $userModel = $this->getMockBuilder(UserModel::class)->disableOriginalConstructor()->getMock();
     $coreParametersHelper = $this->getMockBuilder(CoreParametersHelper::class)->disableOriginalConstructor()->getMock();
     // Setup the translator
     $translator = $this->getMockBuilder(Translator::class)->disableOriginalConstructor()->getMock();
     $translator->expects($this->any())->method('has')->will($this->returnValue(false));
     // Setup the StatRepository
     $statRepository = $this->getMockBuilder(StatRepository::class)->disableOriginalConstructor()->getMock();
     $statRepository->expects($this->once())->method('getTableAlias')->will($this->returnValue('s'));
     $leadEntity = $this->getMockBuilder(Lead::class)->disableOriginalConstructor()->getMock();
     $leadEntity->expects($this->any())->method('getId')->will($this->returnValue(1));
     $emailEntity = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
     $emailEntity->expects($this->any())->method('getId')->will($this->returnValue(1));
     $statEntity = new Stat();
     $statEntity->setTrackingHash('xyz123');
     $statEntity->setLead($leadEntity);
     $statEntity->setEmail($emailEntity);
     $statRepository->expects($this->any())->method('getEntities')->will($this->returnValue([$statEntity]));
     // Setup the EntityManager
     $entityManager = $this->getMockBuilder(EntityManager::class)->disableOriginalConstructor()->getMock();
     $entityManager->expects($this->any())->method('getRepository')->will($this->returnValueMap([['MauticEmailBundle:Stat', $statRepository]]));
     $entityManager->expects($this->any())->method('getReference')->will($this->returnValue($leadEntity));
     $messageModel = $this->getMockBuilder(MessageQueueModel::class)->disableOriginalConstructor()->getMock();
     $companyModel = $this->getMockBuilder(CompanyModel::class)->disableOriginalConstructor()->getMock();
     $companyRepository = $this->getMockBuilder(CompanyRepository::class)->disableOriginalConstructor()->getMock();
     $companyRepository->method('getCompaniesForContacts')->will($this->returnValue([]));
     $companyModel->method('getRepository')->willReturn($companyRepository);
     $emailModel = new \Mautic\EmailBundle\Model\EmailModel($ipLookupHelper, $themeHelper, $mailboxHelper, $mailHelper, $leadModel, $companyModel, $trackableModel, $userModel, $coreParametersHelper, $messageModel);
     $emailModel->setTranslator($translator);
     $emailModel->setEntityManager($entityManager);
     $response = [2 => ['hashIds' => ['xyz123' => 'some reason', '123xyz' => 'some reason']]];
     $dnc = $emailModel->processMailerCallback($response);
     $this->assertCount(1, $dnc);
 }
Beispiel #4
0
 /**
  * Create an email stat
  */
 public function createLeadEmailStat()
 {
     if (!$this->lead) {
         return;
     }
     //create a stat
     $stat = new Stat();
     $stat->setDateSent(new \DateTime());
     $stat->setEmail($this->email);
     $stat->setLead($this->factory->getEntityManager()->getReference('MauticLeadBundle:Lead', $this->lead['id']));
     $stat->setEmailAddress($this->lead['email']);
     $stat->setTrackingHash($this->idHash);
     if (!empty($this->source)) {
         $stat->setSource($this->source[0]);
         $stat->setSourceId($this->source[1]);
     }
     $stat->setCopy($this->getBody());
     $stat->setTokens($this->getTokens());
     /** @var \Mautic\EmailBundle\Model\EmailModel $emailModel */
     $emailModel = $this->factory->getModel('email');
     $emailModel->getStatRepository()->saveEntity($stat);
 }
Beispiel #5
0
 /**
  * Send an email to lead(s)
  *
  * @param       $email
  * @param       $users
  * @param mixed $lead
  * @param array $tokens
  * @param array $assetAttachments
  *
  * @return mixed
  * @throws \Doctrine\ORM\ORMException
  */
 public function sendEmailToUser($email, $users, $lead = null, $tokens = array(), $assetAttachments = array())
 {
     if (!($emailId = $email->getId())) {
         return false;
     }
     if (!is_array($users)) {
         $user = array('id' => $users);
         $users = array($user);
     }
     //get email settings
     $emailSettings = $this->getEmailSettings($email, false);
     //noone to send to so bail
     if (empty($users)) {
         return false;
     }
     $mailer = $this->factory->getMailer();
     $mailer->setLead($lead, true);
     $mailer->setTokens($tokens);
     $mailer->setEmail($email, false, $emailSettings[$emailId]['slots'], $assetAttachments);
     $mailer->useMailerTokenization();
     foreach ($users as $user) {
         $idHash = uniqid();
         $mailer->setIdHash($idHash);
         if (!is_array($user)) {
             $id = $user;
             $user = array('id' => $id);
         } else {
             $id = $user['id'];
         }
         if (!isset($user['email'])) {
             /** @var \Mautic\UserBundle\Model\UserModel $model */
             $userModel = $this->factory->getModel('user');
             $userEntity = $userModel->getEntity($id);
             $user['email'] = $userEntity->getEmail();
             $user['firstname'] = $userEntity->getFirstName();
             $user['lastname'] = $userEntity->getLastName();
         }
         $mailer->setTo($user['email'], $user['firstname'] . ' ' . $user['lastname']);
         $mailer->queue();
         //create a stat
         $stat = new Stat();
         $stat->setDateSent(new \DateTime());
         $stat->setEmail($email);
         $stat->setEmailAddress($user['email']);
         $stat->setTrackingHash($idHash);
         if (!empty($source)) {
             $stat->setSource($source[0]);
             $stat->setSourceId($source[1]);
         }
         $stat->setCopy($mailer->getBody());
         $stat->setTokens($mailer->getTokens());
         $saveEntities[] = $stat;
     }
     //flush the message
     $mailer->flushQueue();
     if (isset($saveEntities)) {
         $this->getStatRepository()->saveEntities($saveEntities);
     }
     //save some memory
     unset($mailer);
 }
 /**
  * {@inheritDoc}
  */
 public function setEmail(\Mautic\EmailBundle\Entity\Email $email = NULL)
 {
     $this->__initializer__ && $this->__initializer__->__invoke($this, 'setEmail', array($email));
     return parent::setEmail($email);
 }