Im struggling to make a code that sends email to my subscribed users. I want to pass body to view according to users default language, can anyone help me ?
My code:
if($newsletter->save())
{
//get users to send to
$users = User::where('newsletter', '=', '1')->Where('activated', '=', '1')->get();
//Send to all users subscribed
foreach($users as $user)
{
//set info according to user default lang
if($user->default_lang == 'pt')
{
$body = $newsletter_pt;
$subject = Input::get('subject_PT');
}
elseif($user->default_lang == 'de')
{
$body = $newsletter_de;
Input::get('subject_DE');
}
$data = array(
'body' => $body,
'subject' => $subject
);
$from_name = Input::get('from_name');
$from_email = Input::get('from_email');
//QUEUE The Newsletters to send
Mail::queue('admin.newsletters.template1', $data, function($message) use ($user, $subject, $from_name, $from_email)
{
$message->from($from_email, $from_name);
$message->bcc($user->email, $user->name);
$message->subject($subject);
});
} //end foreach
return Redirect::To('admin/newsletters')->with('message', array("1" => "Newsletter enviada com sucesso !"));
}
Thanks a lot ;)
Ensure that the $data array has the information you expect to pass into the view before you call Mail::queue(). It should pass both a $body and $subject variable to your view.
You might also try using Mail::send() instead of Mail::queue() and see if it makes a difference (if you're not using a queueing system). Sometimes the queue() method can trip up when serializing Eloquent models, so if $newsletter_pt or $newsletter_de are Eloquent models they might not make it to the view intact.
Related
Our site uses Kohana and php and we are using sendgrid to send transactional emails. With gmail we're having a ton of spam issues and we only send opt-in emails and have a high open rate. One of the potential issues is that our emails seem to have TWO return-paths in the header:
Is being set by us in Kohana
is being inserted by sendgrid.
Sendgrid says that when they send a message, they take over that 'envelope from' for the sake of handling Bounce management. But we can't figure out a way to have Kohana not insert this. Any suggestions? CODE EXAMPLE:
Kohana uses Swift to send mails. How we send them now is below. We've tried removing reply-to via
$message->headers->set('reply-to', '');
but it doesn't appear to work. Funny enough, setting it to a non-empty value alters it, but there doesn't seem to be a way to get rid of it altogether.
Full code for this function:
/**
* Send an email message.
*
* #param string|array recipient email (and name), or an array of To, Cc, Bcc names
* #param string|array sender email (and name)
* #param string message subject
* #param string message body
* #param boolean send email as HTML
* #param string Reply To address. Optional, default null, which defaults to From address
* #return integer number of emails sent
*/
public static function send($category, $to, $from, $subject, $message, $html = FALSE, $replyto = null)
{
// Connect to SwiftMailer
(email::$mail === NULL) and email::connect();
// Determine the message type
$html = ($html === TRUE) ? 'text/html' : 'text/plain';
// Append mixpanel tracking pixel to html emails
if ($html) {
$mixpanel_token = FD_DEV_MODE ? "08c59f4e26aa718a1038459af75aa559" : "d863dc1a3a6242dceee1435c0a50e5b7";
$json_array = '{ "event": "e-mail opened", "properties": { "distinct_id": "' . $to . '", "token": "' . $mixpanel_token . '", "time": ' . time() . ', "campaign": "' . $category . '"}}';
$message .= '<img src="http://api.mixpanel.com/track/?data=' . base64_encode($json_array) . '&ip=1&img=1"></img>';
}
// Create the message
$message = new Swift_Message($subject, $message, $html, '8bit', 'utf-8');
// Adding header for SendGrid, added by David Murray
$message->headers->set('X-SMTPAPI', '{"category" : "' . $category . '"}');
if (is_string($to))
{
// Single recipient
$recipients = new Swift_Address($to);
}
elseif (is_array($to))
{
if (isset($to[0]) AND isset($to[1]))
{
// Create To: address set
$to = array('to' => $to);
}
// Create a list of recipients
$recipients = new Swift_RecipientList;
foreach ($to as $method => $set)
{
if ( ! in_array($method, array('to', 'cc', 'bcc')))
{
// Use To: by default
$method = 'to';
}
// Create method name
$method = 'add'.ucfirst($method);
if (is_array($set))
{
// Add a recipient with name
$recipients->$method($set[0], $set[1]);
}
else
{
// Add a recipient without name
$recipients->$method($set);
}
}
}
if (is_string($from))
{
// From without a name
$from = new Swift_Address($from);
}
elseif (is_array($from))
{
// From with a name
$from = new Swift_Address($from[0], $from[1]);
}
// Reply To support, not standard in Swift, added by Soham
if (!$replyto) $replyto = $from;
$message->setReplyTo($replyto);
return email::$mail->send($message, $recipients, $from);
}
This is not really a Kohana question but more of a Swiftmailer question, since Swiftmailer comes not standard with the Kohana Framework. According to the Swiftmailer docs you can set/get the Return-Path explicitly:
$message->setReturnPath('bounces#address.tld');
Hopes this helps!
i just wanna say thank you for providing this solution for me, indirectly..
// Adding header for SendGrid, added by David Murray
$message->headers->set('X-SMTPAPI', '{"category" : "INSERT CATEGORY HERE"}');
X-SMTPAPI usage documentation from Sendgrid's Website is sucks..
I try to create emails for next sending with my cron php script.
And I use Zend_View for rendering email template.
I have 50k users but 3000 emails was created with 64MB memory limit and 7200 with 128MB.
Code of rendering emails
public function prepareEmailBody($template, $templates)
{
$view = new Zend_View(array('basePath' => './application/views'));
$template_file_name = $template . '.phtml';
foreach ($templates as $key => $value) {
$view->$key = $value;
}
$body = $view->render('mails/' . $template_file_name);
return $body
}
And use this method in
foreach ($users as $user) {
.....
$text = Mailer::getInstance()->prepareEmailBody($template, $vars);
.....
}
Please advice how optimize code.
You could try using one View object and the partial helper instead, this might improve things (or might make it slower).
public function getView()
{
if (!$this->_view) {
$this->_view = new Zend_View(array('basePath' => './application/views'));
}
return $this->_view;
}
public function prepareEmailBody($template, $templates)
{
$template_file_name = $template . '.phtml';
$body = $this->getView()->partial($template_file_name, $templates);
return $body
}
I'm currently working on a reminder PHP Script which will be called via Cronjob once a day in order to inform customers about smth.
Therefore I'm using the PEAR Mail function, combined with Mail_Mime. Firstly the script searches for users in a mysql database. If $num_rows > 0, it's creating a new Mail object and a new Mail_mime object (the code encluded in this posts starts at this point). The problem now appears in the while-loop.
To be exact: The problem is
$mime->headers($headers, true);
As the doc. states, the second argument should overwrite the old headers. However all outgoing mails are sent with the header ($header['To']) from the first user.
I'm really going crazy about this thing... any suggestions?
(Note: However it's sending the correct headers when calling $mime = new Mail_mime() for each user - but it should work with calling it only once and then overwriting the old headers)
Code:
// sql query and if num_rows > 0 ....
require_once('/usr/local/lib/php/Mail.php');
require_once('/usr/local/lib/php/Mail/mime.php');
ob_start();
require_once($inclPath.'/email/head.php');
$head = ob_get_clean();
ob_start();
require_once($inclPath.'/email/foot.php');
$foot = ob_get_clean();
$XY['mail']['params']['driver'] = 'smtp';
$XY['mail']['params']['host'] = 'smtp.XY.at';
$XY['mail']['params']['port'] = 25;
$mail =& Mail::factory('smtp', $XY['mail']['params']);
$headers = array();
$headers['From'] = 'XY <service#XY.at>';
$headers['Subject'] = '=?UTF-8?B?'.base64_encode('Subject').'?=';
$headers['Reply-To'] = 'XY <service#XY.at>';
ob_start();
require_once($inclPath.'/email/templates/files.mail.require-review.php');
$template = ob_get_clean();
$crfl = "\n";
$mime = new Mail_mime($crfl);
while($row = $r->fetch_assoc()){
$html = $head . $template . $foot;
$mime->setHTMLBody($html);
#$to = '=?UTF-8?B?'.base64_encode($row['firstname'].' '.$row['lastname']).'?= <'.$row['email'].'>'; // for testing purpose i'm sending all mails to webmaster#XY.at
$to = '=?UTF-8?B?'.base64_encode($row['firstname'].' '.$row['lastname']).'?= <webmaster#XY.at>';
$headers['To'] = $to; // Sets to in headers to a new
$body = $mime->get(array('head_charset' => 'UTF-8', 'text_charset' => 'UTF-8', 'html_charset' => 'UTF-8'));
$hdrs = $mime->headers($headers, true); // although the second parameters says true, the second, thrid, ... mail still includes the To-header form the first user
$sent = $mail->send($to, $hdrs, $body);
if (PEAR::isError($sent)) {
errlog('error while sending to user_id: '.$row['id']); // personal error function
} else {
// Write log file
}
}
There is no reason to keep the old object and not creating a new one.
Use OOP properly and create new objects - you do not know how they work internally.
Is there any class in the Zend Framework that allows me to easily read emails?
The Zend_Mail class does allow me to easy get headers, subject and the content body. But transferring everything to UTF-8 and human-readable format is still a pain.
Or am I doing something wrong? As far as I can tell, Zend Framework does not allow me to easily get UTF-8 strings that I can just use, I still have to do some post-processing. Right?
The key thing is that you need to iterate over the parts within the Message and find the text. Once you have it, then you can use quoted_printable_decode to get the text itself in a useful way.
This is some rough and ready code that reads IMAP email boxes with Zend_Mail:
<?php
$mail = new Zend_Mail_Storage_Imap(array(
'host' => EMAIL_ACCOUNT_HOST,
'user' => EMAIL_ACCOUNT_USERNAME,
'password' => EMAIL_ACCOUNT_PASSWORD,
));
echo (int)$mail->countMessages() . " messages found\n";
foreach ($mail as $message) {
$from = $message->getHeader('from');
$subject = trim($message->subject);
$to = trim($message->to);
$body = getBody($message);
// do something with message here
}
function getBody(Zend_Mail_Message $message)
{
// find body
$part = $message;
$isText = true;
while ($part->isMultipart()) {
$foundPart = false;
$iterator = new RecursiveIteratorIterator($message);
foreach ($iterator as $part) {
// this detection code is a bit rough and ready!
if (!$foundPart) {
if (strtok($part->contentType, ';') == 'text/html') {
$foundPart = $part;
$isText = false;
break;
} else if (strtok($part->contentType, ';') == 'text/plain') {
$foundPart = $part;
$isText = true;
break;
}
}
}
if($foundPart) {
$part = $foundPart;
break;
}
}
$body = quoted_printable_decode($part->getContent());
}
I have created a custom script to import a bulk number of customers to magento database. What client needed is for each 100 customers import they needed a mail about whats going on and status of the importing.
So how can i use the magento mailing functionality so that i can create a template to send mail as like magento does. Please help me
I think you're looking for something along the following lines:
$store_id = $this->getStoreId();
$template = "import_script_email_template_name";
$from = Mage::getStoreConfig(self::XML_PATH_EMAIL_IDENTITY, $store_id);
$to = array( "name" => "Nick", "email" => "the#email.address" );
$template_variables = array(
"var1" => "somevalue",
"var2" => "someothervalue"
);
$mail = Mage::getModel("core/email_template");
$mail->setDesignConfig( array( "area" => "frontend", "store" => $store_id ))
->sendTransactional(
$template_name,
$from,
$to["email"],
$to["name"],
$template_variables
);
Note: This was lifted from Mage_Sales_Model_Order::sendNewOrderEmail() and hasn't been tested, but it should be more than enough to get you started. Treat it as pseudo-code :)
If you are just doing this from an import script, the PHP mail function should be more than sufficient.
Also can do the mailing functionality of ZEND
Here is the code
$mail_body = "<h3> These are ordered by you in the event - '".$customer_event."' </h3> <br/>". $email_body;
$to_email = $email;
$to_name = $customer_name;
$subject = 'Orders';
$Body = $body;
$sender_email = "info#mail.com";
$sender_name = "mail";
$html = new Zend_View();
$html->setScriptPath('app/locale/en_US/template/email/');
$html->assign('customer_name', $customer_name);
$html->assign('email', $to_email);
$html->assign('password', $password);
$html->assign('site_url', Mage::getUrl(""));
$html->assign('site_skin_url', Mage::getDesign()->getSkinUrl("images/"));
$html->assign('site_order_url', Mage::getUrl("").'Event.php?id='.$id.'&cart_id='.$cart_id);
$html->assign('site_name', 'Winecellarage');
$html->assign('site_data', $mail_body);
$Body_text= $html->render($template);
$mail = new Zend_Mail('utf-8');
$mail->setBodyHtml($Body_text);
$mail->setFrom($sender_email, $sender_name);
$mail->addTo($to_email, $to_name);
//$mail->addCc($cc, $ccname);
//$mail->addBCc($bcc, $bccname);
$mail->setSubject($subject);
try {
if($mail->send())
{
$msg .= "<p>Mail sent successfully to '$to_email' </p>";
}
}
catch(Exception $ex) {
$err .= '<p>'.$error_msg = $ex->getMessage()."</p>";
}
This one is working exactly what i wanted. So may be useful to some one.