/** * Returns MailHelper wrapper for Swift_Message via $helper->message * * @param bool $cleanSlate False to preserve current settings, i.e. to process batched emails * * @return MailHelper */ public function getMailer($cleanSlate = true) { if ($this->mailHelper == null) { $this->mailHelper = new MailHelper($this, $this->container->get('mailer'), array($this->getParameter('mailer_from_email') => $this->getParameter('mailer_from_name'))); } else { $this->mailHelper->reset($cleanSlate); } return $this->mailHelper; }
public function indexAction($idHash) { /** @var \Mautic\EmailBundle\Model\EmailModel $model */ $model = $this->factory->getModel('email'); $translator = $this->get('translator'); $stat = $model->getEmailStatus($idHash); if (!empty($stat)) { $entity = $stat->getEmail(); $model->hitEmail($stat, $this->request, true); // Check for stored copy $content = $stat->getCopy(); if (!empty($content)) { // Copy stored in stats $tokens = $stat->getTokens(); if (!empty($tokens)) { // Override tracking_pixel so as to not cause a double hit $tokens['{tracking_pixel}'] = MailHelper::getBlankPixel(); $content = str_ireplace(array_keys($tokens), $tokens, $content); } } else { // Old way where stats didn't store content //the lead needs to have fields populated $statLead = $stat->getLead(); $lead = $this->factory->getModel('lead')->getLead($statLead->getId()); $template = $entity->getTemplate(); if (!empty($template)) { $slots = $this->factory->getTheme($template)->getSlots('email'); $response = $this->render('MauticEmailBundle::public.html.php', array('inBrowser' => true, 'slots' => $slots, 'content' => $entity->getContent(), 'email' => $entity, 'lead' => $lead, 'template' => $template)); //replace tokens $content = $response->getContent(); } else { $content = $entity->getCustomHtml(); } $content = EmojiHelper::toEmoji($content, 'short'); $tokens = $stat->getTokens(); // Override tracking_pixel so as to not cause a double hit $tokens['{tracking_pixel}'] = MailHelper::getBlankPixel(); $event = new EmailSendEvent(array('content' => $content, 'lead' => $lead, 'email' => $entity, 'idHash' => $idHash, 'tokens' => $tokens)); $this->factory->getDispatcher()->dispatch(EmailEvents::EMAIL_ON_DISPLAY, $event); $content = $event->getContent(true); } $analytics = htmlspecialchars_decode($this->factory->getParameter('google_analytics', '')); // Check for html doc if (strpos($content, '<html>') === false) { $content = "<html>\n<head>{$analytics}</head>\n<body>{$content}</body>\n</html>"; } elseif (strpos($content, '<head>') === false) { $content = str_replace('<html>', "<html>\n<head>\n{$analytics}\n</head>", $content); } elseif (!empty($analytics)) { $content = str_replace('</head>', $analytics . "\n</head>", $content); } return new Response($content); } throw $this->createNotFoundException($translator->trans('mautic.core.url.error.404')); }
/** * {@inheritdoc} */ protected function getPayload() { $metadata = $this->getMetadata(); $mauticTokens = $mandrillMergeVars = $mandrillMergePlaceholders = array(); // Mandrill uses *|PLACEHOLDER|* for tokens so Mautic's need to be replaced if (!empty($metadata)) { $metadataSet = reset($metadata); $tokens = !empty($metadataSet['tokens']) ? $metadataSet['tokens'] : array(); $mauticTokens = array_keys($tokens); $mandrillMergeVars = $mandrillMergePlaceholders = array(); foreach ($mauticTokens as $token) { $mandrillMergeVars[$token] = strtoupper(preg_replace("/[^a-z0-9]+/i", "", $token)); $mandrillMergePlaceholders[$token] = '*|' . $mandrillMergeVars[$token] . '|*'; } } $message = $this->messageToArray($mauticTokens, $mandrillMergePlaceholders); $message['from_email'] = $message['from']['email']; $message['from_name'] = $message['from']['name']; unset($message['from']); if (!empty($metadata)) { // Mandrill will only send a single email to cc and bcc of the first set of tokens // so we have to manually set them as to addresses // Problem is that it's not easy to know what email is sent so will tack it at the top $insertCcEmailHeader = true; $message['html'] = '*|HTMLCCEMAILHEADER|*' . $message['html']; if (!empty($message['text'])) { $message['text'] = '*|TEXTCCEMAILHEADER|*' . $message['text']; } // Do not expose all the emails in the if using metadata $message['preserve_recipients'] = false; $bcc = $message['recipients']['bcc']; $cc = $message['recipients']['cc']; // Unset the cc and bcc as they will need to be sent as To with each set of tokens unset($message['recipients']['bcc'], $message['recipients']['cc']); } // Generate the recipients $recipients = $rcptMergeVars = $rcptMetadata = array(); $translator = $this->factory->getTranslator(); foreach ($message['recipients'] as $type => $typeRecipients) { foreach ($typeRecipients as $rcpt) { $rcpt['type'] = $type; $recipients[] = $rcpt; if ($type == 'to' && isset($metadata[$rcpt['email']])) { if (!empty($metadata[$rcpt['email']]['tokens'])) { $mergeVars = array('rcpt' => $rcpt['email'], 'vars' => array()); // This must not be included for CC and BCCs $trackingPixelToken = array(); foreach ($metadata[$rcpt['email']]['tokens'] as $token => $value) { if ($token == '{tracking_pixel}') { $trackingPixelToken = array(array('name' => $mandrillMergeVars[$token], 'content' => $value)); continue; } $mergeVars['vars'][] = array('name' => $mandrillMergeVars[$token], 'content' => $value); } if (!empty($insertCcEmailHeader)) { // Make a copy before inserted the blank tokens $ccMergeVars = $mergeVars; $mergeVars['vars'] = array_merge($mergeVars['vars'], $trackingPixelToken, array(array('name' => 'HTMLCCEMAILHEADER', 'content' => ''), array('name' => 'TEXTCCEMAILHEADER', 'content' => ''))); } else { // Just merge the tracking pixel tokens $mergeVars['vars'] = array_merge($mergeVars['vars'], $trackingPixelToken); } // Add the vars $rcptMergeVars[] = $mergeVars; // Special handling of CC and BCC with tokens if (!empty($cc) || !empty($bcc)) { $ccMergeVars['vars'] = array_merge($ccMergeVars['vars'], array(array('name' => 'HTMLCCEMAILHEADER', 'content' => $translator->trans('mautic.core.email.cc.copy', array('%email%' => $rcpt['email'])) . "<br /><br />"), array('name' => 'TEXTCCEMAILHEADER', 'content' => $translator->trans('mautic.core.email.cc.copy', array('%email%' => $rcpt['email'])) . "\n\n"), array('name' => 'TRACKINGPIXEL', 'content' => MailHelper::getBlankPixel()))); // Send same tokens to each CC if (!empty($cc)) { foreach ($cc as $ccRcpt) { $recipients[] = $ccRcpt; $ccMergeVars['rcpt'] = $ccRcpt['email']; $rcptMergeVars[] = $ccMergeVars; } } // And same to BCC if (!empty($bcc)) { foreach ($bcc as $ccRcpt) { $recipients[] = $ccRcpt; $ccMergeVars['rcpt'] = $ccRcpt['email']; $rcptMergeVars[] = $ccMergeVars; } } } unset($ccMergeVars, $mergeVars, $metadata[$rcpt['email']]['tokens']); } if (!empty($metadata[$rcpt['email']])) { $rcptMetadata[] = array('rcpt' => $rcpt['email'], 'values' => $metadata[$rcpt['email']]); unset($metadata[$rcpt['email']]); } } } } $message['to'] = $recipients; unset($message['recipients']); // Set the merge vars $message['merge_vars'] = $rcptMergeVars; // Set the rest of $metadata as recipient_metadata $message['recipient_metadata'] = $rcptMetadata; // Set the reply to if (!empty($message['replyTo'])) { $message['headers']['Reply-To'] = $message['replyTo']['email']; } unset($message['replyTo']); // Package it up $payload = json_encode(array('key' => $this->getPassword(), 'message' => $message)); return $payload; }
/** * @return array */ public function getSource() { return $this->helper !== null ? $this->helper->getSource() : $this->source; }
/** * Converts \Swift_Message into associative array * * @param array $search If the mailer requires tokens in another format than Mautic's, pass array of Mautic tokens to replace * @param array $replace If the mailer requires tokens in another format than Mautic's, pass array of replacement tokens * * @return array|\Swift_Message */ protected function messageToArray($search = array(), $replace = array()) { if (!empty($search)) { MailHelper::searchReplaceTokens($search, $replace, $this->message); } $from = $this->message->getFrom(); $fromEmail = current(array_keys($from)); $fromName = $from[$fromEmail]; $message = array('html' => $this->message->getBody(), 'text' => MailHelper::getPlainTextFromMessage($this->message), 'subject' => $this->message->getSubject(), 'from' => array('name' => $fromName, 'email' => $fromEmail)); // Generate the recipients $message['recipients'] = array('to' => array(), 'cc' => array(), 'bcc' => array()); $to = $this->message->getTo(); foreach ($to as $email => $name) { $message['recipients']['to'][$email] = array('email' => $email, 'name' => $name); } $cc = $this->message->getCc(); if (!empty($cc)) { foreach ($cc as $email => $name) { $message['recipients']['cc'][$email] = array('email' => $email, 'name' => $name); } } $bcc = $this->message->getBcc(); if (!empty($bcc)) { foreach ($bcc as $email => $name) { $message['recipients']['bcc'][$email] = array('email' => $email, 'name' => $name); } } $replyTo = $this->message->getReplyTo(); if (!empty($replyTo)) { foreach ($replyTo as $email => $name) { $message['replyTo'] = array('email' => $email, 'name' => $name); } } // Attachments $children = $this->message->getChildren(); $attachments = array(); foreach ($children as $child) { if ($child instanceof \Swift_Attachment) { $attachments[] = array('type' => $child->getContentType(), 'name' => $child->getFilename(), 'content' => $child->getEncoder()->encodeString($child->getBody())); } } $message['attachments'] = $attachments; return $message; }
/** * @param $fields * @param $data * @param null $owner * @param null $list * @param bool $persist Persist to the database; otherwise return entity * * @return bool * @throws \Doctrine\ORM\ORMException * @throws \Swift_RfcComplianceException */ public function importLead($fields, $data, $owner = null, $list = null, $persist = true) { // Let's check for an existing lead by email $hasEmail = !empty($fields['email']) && !empty($data[$fields['email']]); if ($hasEmail) { // Validate the email MailHelper::validateEmail($data[$fields['email']]); $leadFound = $this->getRepository()->getLeadByEmail($data[$fields['email']]); $lead = $leadFound ? $this->em->getReference('MauticLeadBundle:Lead', $leadFound['id']) : new Lead(); $merged = $leadFound; } else { $lead = new Lead(); $merged = false; } if (!empty($fields['dateAdded']) && !empty($data[$fields['dateAdded']])) { $dateAdded = new DateTimeHelper($data[$fields['dateAdded']]); $lead->setDateAdded($dateAdded->getUtcDateTime()); } unset($fields['dateAdded']); if (!empty($fields['dateModified']) && !empty($data[$fields['dateModified']])) { $dateModified = new DateTimeHelper($data[$fields['dateModified']]); $lead->setDateModified($dateModified->getUtcDateTime()); } unset($fields['dateModified']); if (!empty($fields['lastActive']) && !empty($data[$fields['lastActive']])) { $lastActive = new DateTimeHelper($data[$fields['lastActive']]); $lead->setLastActive($lastActive->getUtcDateTime()); } unset($fields['lastActive']); if (!empty($fields['dateIdentified']) && !empty($data[$fields['dateIdentified']])) { $dateIdentified = new DateTimeHelper($data[$fields['dateIdentified']]); $lead->setDateIdentified($dateIdentified->getUtcDateTime()); } unset($fields['dateIdentified']); if (!empty($fields['createdByUser']) && !empty($data[$fields['createdByUser']])) { $userRepo = $this->em->getRepository('MauticUserBundle:User'); $createdByUser = $userRepo->findByIdentifier($data[$fields['createdByUser']]); if ($createdByUser !== null) { $lead->setCreatedBy($createdByUser); } } unset($fields['createdByUser']); if (!empty($fields['modifiedByUser']) && !empty($data[$fields['modifiedByUser']])) { $userRepo = $this->em->getRepository('MauticUserBundle:User'); $modifiedByUser = $userRepo->findByIdentifier($data[$fields['modifiedByUser']]); if ($modifiedByUser !== null) { $lead->setModifiedBy($modifiedByUser); } } unset($fields['modifiedByUser']); if (!empty($fields['ip']) && !empty($data[$fields['ip']])) { $addresses = explode(',', $data[$fields['ip']]); foreach ($addresses as $address) { $ipAddress = new IpAddress(); $ipAddress->setIpAddress(trim($address)); $lead->addIpAddress($ipAddress); } } unset($fields['ip']); if (!empty($fields['points']) && !empty($data[$fields['points']]) && $lead->getId() === null) { // Add points only for new leads $lead->setPoints($data[$fields['points']]); //add a lead point change log $log = new PointsChangeLog(); $log->setDelta($data[$fields['points']]); $log->setLead($lead); $log->setType('lead'); $log->setEventName($this->factory->getTranslator()->trans('mautic.lead.import.event.name')); $log->setActionName($this->factory->getTranslator()->trans('mautic.lead.import.action.name', array('%name%' => $this->factory->getUser()->getUsername()))); $log->setIpAddress($this->factory->getIpAddress()); $log->setDateAdded(new \DateTime()); $lead->addPointsChangeLog($log); } unset($fields['points']); if (!empty($fields['doNotEmail']) && !empty($data[$fields['doNotEmail']]) && $hasEmail) { $doNotEmail = filter_var($data[$fields['doNotEmail']], FILTER_VALIDATE_BOOLEAN); if ($doNotEmail) { $reason = $this->factory->getTranslator()->trans('mautic.lead.import.by.user', array("%user%" => $this->factory->getUser()->getUsername())); $dnc = $this->setDoNotContact($lead, $data[$fields['email']], $reason, false); $lead->addDoNotEmailEntry($dnc); } } unset($fields['doNotEmail']); if ($owner !== null) { $lead->setOwner($this->em->getReference('MauticUserBundle:User', $owner)); } foreach ($fields as $leadField => $importField) { // Prevent overwriting existing data with empty data if (array_key_exists($importField, $data) && !is_null($data[$importField]) && $data[$importField] != '') { $lead->addUpdatedField($leadField, $data[$importField]); } } $lead->imported = true; if ($persist) { $this->saveEntity($lead); if ($list !== null) { $this->addToLists($lead, array($list)); } } return $merged; }