I have a custom module that I'm trying to generate an HTML email from using the drupal_mail function (D7). Mail is coming through, and even shows text/html, however something somewhere appears to be stripping out the HTMl before it gets to an inbox.
First, in a function I'm building my title/body/other vars and sending to a custom function:
$body = "We thought you'd like to know that ".$fullname." has marked your project as completed.
<br /><br />
Please visit the link at <a href='http://".$_SERVER['HTTP_HOST']."/survey/customer/".$customer[0]->unique_id."'>http://".$_SERVER['HTTP_HOST']."/survey/customer/".$customer[0]->unique_id."</a> to take the survey.";
$returnMail = latch_send_mail('pro_realized',$customer[0]->customer_email,$user->mail,$title,$body);
Then I have the latch_mail latch_send_email functions:
function latch_mail($key, &$message, $params) {
$headers = array(
'MIME-Version' => '1.0',
'Content-Type' => 'text/html; charset=UTF-8; format=flowed',
'Content-Transfer-Encoding' => '8Bit',
'X-Mailer' => 'Drupal'
);
foreach ($headers as $key => $value) {
$message['headers'][$key] = $value;
}
$message['body'][] = $params['body'];
$message['subject'] = $params['subject'];
}
and
function latch_send_mail($key,$to,$from,$title,$body,$headers='') {
$params['body']=$body;
$params['subject'] = t($title);
return drupal_mail('latch', $key, $to, language_default(), $params, $from,TRUE);
}
I would expect the emails to come through with my a tags and br tags, but it comes through like this:
We thought you'd like to know that John Doe has marked your project as completed. Please visit the link at http://latch.local/survey/customer/34c91b8883cd70b32c65feb7adf9c393 [1] to take the survey. [1] http://latch.local/survey/customer/34c91b8883cd70b32c65feb7adf9c393
Somehow it's taking my links and turning them into footnotes while removing the br tags completely.
Any help you can provide would be appreciated. Thanks!
Out of the box, Drupal can't send HTML email. In order for Drupal to support HTML email you need the HTML Mail module. http://drupal.org/project/htmlmail Once you have that all HTML should be sent as such.
Here's an alternative method with a complete explenation. First of all, install and enable the Mime Mail module. You can read the README.txt for complete instructions on how to use it. I'll give you the short version.
You need to enable Mime Mail for your module. You can do this using hook_enable or hook_update_N in example.install:
function example_enable() {
mailsystem_set(array(
'example_examplekey' => 'MimeMailSystem',
));
}
When you go to admin/config/system/mailsystem you will see that a new entry has been added for your module:
Example module (examplekey key) class
MimeMailSystem
Now you don't need to specificy any text/html headers anymore, Mime Mail takes care of this. So you don't need this:
$headers['Content-Type'] = ...
If you want, you can add $message['plaintext'] to your mail for a non-HTML alternative, but this is not required.
That's it!
Related
I've written a WordPress plugin which sends out new post notifications. There is a setting to convert subject lines from html entites to quoted-printable so they'll display in UTF-8 on any email client. A few weeks ago I started getting reports that the quoted-printable subject line was being kept as-is instead of being decoded.
Sample Subject header:
Subject: =?UTF-8?Q?[Pranamanasyoga]=20Foro=20Pranamanasyoga=20:=20estr?= =?UTF-8?Q?=C3=A9s=20y=20resilencia?=
I cannot replicate it locally and have not been able to find any common denominators between reporters.
The code that generates the quoted-printable line is this:
<?php
$enc = iconv_get_encoding( 'internal_encoding' ); // this is UTF-8
$preferences = ['input-charset' => $enc, 'output-charset' => "UTF-8", 'scheme' => 'Q' ];
$filtered_subject = '[Pranamanasyoga] Foro Pranamanasyoga : estrés y resilencia';
$encoded = iconv_mime_encode( 'Subject', html_entity_decode( $filtered_subject ), $preferences );
$encoded = substr( $encoded, strlen( 'Subject: ' ) );
If I try decoding it, it works fine:
$decoded = iconv_mime_decode($encoded, 0, "UTF-8");
var_dump(['encoded' => $encoded, 'decoded' => $decoded])."\n";
Result:
array(2) {
["encoded"]=>
string(102) "=?UTF-8?Q?[Pranamanasyoga]=20Foro=20Pranamanasyoga=20:=20estr?=
=?UTF-8?Q?=C3=A9s=20y=20resilencia?="
["decoded"]=>
string(59) "[Pranamanasyoga] Foro Pranamanasyoga : estrés y resilencia"
}
One thing I noticed, but think is not related is that my code actually adds a newline before the second =?UTF-8?Q? piece and the email subject header does not have it. Decoding the strings with- and without the newline works the same.
Does anyone have ideas/suggestions on what may be causing the email clients (Gmail included) to display the string as-is, instead of decoding it to UTF-8?
P.S. While writing this I saw a suggestion to use mb_encode_mimeheader() in a different thread. It seems to work well with iconv_mime_decode() in my test code, but the output string is indeed different from the original one:
[Pranamanasyoga] Foro Pranamanasyoga : =?UTF-8?Q?estr=C3=A9s=20y=20resile?=
=?UTF-8?Q?ncia?=
Could it be that email clients would prefer this format over the original one?
Currently I'm writing a script to move emails from a folder to a different folder. All mails containing the X-Priority: 3 header should be moved.
Part of source of the mail:
Date: DATE
To: NAME <EMAIL>
From: "NAME" <EMAIL>
Subject: SUBJECT
Message-ID: <SOMEID#EMAIL>
X-Priority: 3
Code I'm using:
$imapStream = imap_open('{HOST}Sent', 'EMAIL', 'PASSWORD');
$emailIds = imap_search($imapStream, 'ALL');
rsort($emailIds);
foreach ($emailIds as $emailId) {
$overview = imap_fetch_overview($imapStream, $emailId, 0);
$message = imap_fetchtext($imapStream, $emailId, 2);
var_dump($overview); // <-- Doesn't contain X-Priority
die;
}
Now, I need to filter all emails that has the X-Priority header set. I first thought I could maybe check the imap_fetch_overview, imap_fetchtext or imap_fetchbody but none contain the X-Priority. However, the X-Priority isn't a valid imap_search criteria.
How can I filter the mailbox and get only the emails with the X-Priority header?
Okay, I should've looked better before posting but I'll post my findings anyways:
I found out I could get the headers with imap_fetchheader, which also contains the X-Priority header (duh...)
So the code to retrieve it would be:
$headers = explode("\n", imap_fetchheader($imapStream, $emailId, 0));
In case of filtering, I could use TEXT as criteria to filter emails with a certain X-Priority, like this:
$emailIds = imap_search($imapStream, 'TEXT "X-Priority: 3"');
This seems to get all emails containing the X-Priority header only.
Whenever mails are triggered from wordpress site, a few alphabets are randomly getting replaced with '=' in the mail content. I have set the charset and content type in headers even then this weird error is coming. What could be the possible fix to this ?
Below is my code to trigger mails from wordpress site:
$footerText = "<br/><br/>
Regards,<br/>
ABC<br/><br/>
Note: This is an automated mail. Please do not reply to this message";
$post = get_post($postId);
$post_date = strtotime($post->post_date);
$author_email = get_the_author_meta( 'user_email', $post->post_author);
$headers = array();
$headers[] = 'Content-type: text/html; charset=UTF-8';
$headers[] = 'From: '.FROM_EMAIL;
//$headers[] = 'Bcc: '.$author_email;
$subject = "Request to share your expertise on - '".$post->post_title."'";
$post_title = $post->post_title;
$post_content = $post->post_content;
$post_url = get_permalink($post->ID);
$mail_message = "Your expertise would help solve complex business problems that would
help our associates solve our client problems faster.
Request you to share your expertise on the following post,
which has not been answered for over ".$days." days now.<br/><br/>
Post: <strong>".$post_title."</strong><br/>
Description: ".$post_content."<br/><br/>
Click <a href='".$post_url."'>here</a> to respond to the post.<br/><br/>
Thanks You!
".$footerText;
$hello_text = "Dear Expert,<br /><br />";
$full_message = $hello_text.$mail_message;
wp_mail('abc#gmail.com',$subject,$full_message,$headers);
Emails that i receive using this code is as follows:
Dear Expert,
Your expertise would help solve complex business p=oblems that would help our associates solve our Cli=nt(s) problems faster. Request you to share your experti=e on the following post, which has not been answered for o=er 8 days now.
Post: RFP for Business De=elopment,Functional Testing,Technology Expert,Perfecto,Healthcare,Medical =anagement,Mobile,Digital,North America This is Dynamic content, retrieved from database
Description: Customer is asking f=r RFQ to develop a new mobile app for care management application in AHM. =HM is a subsidary of Aetna Inc. This is Dynamic content, retrieved from database
Click here to respond to the post.
Thank you!
Regards, ABC
Note: This is an automated mail.=lease do not reply to this message
Totally confused on why random letters are getting replaced with '='.Kindly point out and suggest what is wrong with this
Commenting couple of return statements and replacing them as suggested in the below link on wordpress.org worked for me, now the mails are sent properly and the equal sign '=' issue is solved.
Fixed by making following changes in wp-includes\class-phpmailer.php
public function encodeQP($string, $line_max = 76)
{
// Use native function if it's available (>= PHP5.3)
if (function_exists('quoted_printable_encode')) {
//return $this->fixEOL(quoted_printable_encode($string)); commented this one
return quoted_printable_encode($string); // added this line
}
// Fall back to a pure PHP implementation
$string = str_replace(
array('%20', '%0D%0A.', '%0D%0A', '%'),
array(' ', "\r\n=2E", "\r\n", '='),
rawurlencode($string)
);
$string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
//return $this->fixEOL($string); commented this one
return $string; // added this line
}
Read more here: https://core.trac.wordpress.org/ticket/33815
I have a PHP script which has the source of an email. I aim to split the headers into variables $To and $From
The issue comes when trying to split the to and from strings up. What I need the script to do is take
From: John <john#somesite.com>
To: Susy <susy#mysite.com>, Steven <steven#somesite.com>, Mary <mary#mysite.com>
and return only the from address and the to addresses which are on my site. I.e.
$From = 'john#somesite.com';
$To = array('susy#mysite.com', 'mary#mysite.com');
So the code needs to turn a string of email addresses into an array and then filter out the ones from other sites. It's the first part that is proving difficult because of the different ways an email address can be listed in a header.
Edit
As you've now specified that you have the headers as a string but you actually need to parse the addresses from it, there is no need to reinvent the wheel:
imap_rfc822_parse_headersDocs
imap_rfc822_parse_adrlistDocs
These two functions will do the job for you, the last one will give you an array with objects that have the email addresses pre-parsed, so you can easily take decisions based on the host.
It was not specifically clear to me what your actual problem is from your question.
As long as you are concerned about filtering a string containing one email address (cast it to array) or an array containing one or multiple addresses:
To filter the existing array of email-addresses you can use a simple array mapping function that will set any email that is not matching your site's host to FALSE and then filter the array copy Demo:
$addresses = array(
'mary#mysite.com',
'mary#othersite.com',
);
$myhost = 'mysite.com';
$filtered = array_map(function($email) use ($myhost) {
$host = '#'.$myhost;
$is = substr($email, -strlen($host)) === $host;
return $is ? $email : FALSE;
}, $addresses);
$filtered = array_filter($filtered);
print_r($filtered);
This codes makes the assumption that you have the email addresses already gathered. You have not specified how you parse the headers already in your question, so it's actually unknown with which data you are dealing, so I opted to start from the end of your problem. Let us know if you have more information available.
<?php
$k= "......Subject: Write the program any of your favorite language whenever if you feel
you are free
From: Vinay Kumar <vinaykumarjg#gmail.com>
To: msnjsk#gmail.com, mithunsatish#gmail.com,Susy <susy#mysite.com>, Steven <steven#somesite.com>, Mary <mary#mysite.com>
Content-Type: multipart/alternative; boundary=bcaec53964ec5eed2604acd0e09a
--bcaec53964ec5eed2604acd0e09a
Content-Type: text/plain; charset=ISO-8859-1
.......";
if(preg_match('/From:(?P<text>.+)\r\n/', $k, $matches1))
{
if(preg_match('/(?P<from>([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\#([a-z0-9])' .'(([a-z0-9-])*([a-z0-9]))+' . '(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+)/', $matches1['text'],$sender ))
{
print_r($sender['from']);
}
}
if(preg_match('/To:(?P<text>.+)\r\n/', $k, $matches2))
{
if(preg_match_all('/(?P<to>([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\#([a-z0-9])' .
'(([a-z0-9-])*([a-z0-9]))+' . '(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+)/', $matches2['text'], $reciever))
{
if(isset($reciever['to']))
{
print_r($reciever['to']);
}
}
}
to get the subject:
if(preg_match('/Subject:(?P<subject>.+)\r\n/', $k, $subject))
{
print_r($subject['subject']);
}
preg_match_all("/<([^><]+)/", $headers, $matches);
print_r($matches[1]);
Output:
Array
(
[0] => john#somesite.com
[1] => susy#mysite.com
[2] => steven#somesite.com
[3] => mary#mysite.com
)
The first one is always From email address.
Live demo
Nightmare Episode 1
I put 21 hours today to solve this. But i failed, asking experts to have a look, checked almost PEAR all possibilities but this Microsoft Outlook never gives up. What is this secret ?
Microsoft Outlook 2010 as receives as junk email when i put junk filter to "High". If i send another email with my same account from Google it goes to Inbox.
What is the problem with this Outlook ? I tried to follow multipart/alternative or multipart/mixed or multipart/relative but all Same.
My server log shows: 100% ok no spam not blacklist, all clear
Dec 8 15:42:30 www postfix/smtp[15250]: C99908162: to=, relay=mail.andmylab.com[01.01.01.01]:25, delay=0.25, delays=0.07/0.01/0.08/0.09, dsn=2.0.0, status=sent (250 OK id=1PQQqL-0001b6-TA)
My blacklist: www.whatismyipaddress.com shows no black list all green
- I can send to Google or to my own domain and other domain without any problems.
My code: its generating exactly multipart/alternative where i am following RFC standards
/* DB details */
$config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/cloude.ini', 'production');
define("DBHOST", $config->resources->db->params->host);
define("DBUSER", $config->resources->db->params->username);
define("DBPASS", $config->resources->db->params->password);
define("DEFAULT_DB", $config->resources->db->params->dbname);
define("MAILER_TABLE", "mail_queue");
/* 1 --------------------- PEAR!! */
require_once "Mail/Queue.php";
require_once 'Mail/mime.php';
require_once 'Mail/mimePart.php';
/* 2 --------------------- DB */
$db_options['type'] = 'db';
$db_options['dsn'] = 'mysql://' . DBUSER . ":" . DBPASS . "#" . DBHOST . "/" . DEFAULT_DB;
$db_options['mail_table'] = MAILER_TABLE;
$mail_options['driver'] = 'mail';
/* Step ------------------ 1 */
$mail_queue =& new Mail_Queue($db_options, $mail_options);
$from = "validguy#lul.be";
/* Step ------------------ 2 */
$mime =& new Mail_mime($crlf = "\n");
$mail =& Mail::factory($mail_options['driver']);
/* Step ------------------ 3 Plain text and Html */
$data->mode = 'html';
if ($data->mode=='html')
{
/* A <--------------- part */
$params['content_type'] = 'multipart/alternative';
$email = new Mail_mimePart('', $params);
/* B <--------------- part */
$email = $email->encode();
$email['headers']['Mime-Version'] = '1.0';
$email['headers']['Subject'] = $fix;
$email['headers']['From'] = $from;
//Zend_Debug::dump($email);
// exit;
/* C <--------------- part */
$mime->setTXTBody('Test');
$mime->setHTMLBody($txt2);
/* D <--------------- part */
$body = $mime->get();
$hdrs = $mime->headers($email['headers']);
} else if($data->mode=='both') {
// later... for multipart/relative
} else {
// later... for inline
}
/* Step 4 - done */
$mailResult = $mail_queue->put($from, $row->email, $hdrs, $body, 0,true,$nres[0]['id']);
//$mailResult = $mail_queue->put($from, $row->email, $email['headers'], $email['body'], 0,true,$nres[0]['id']);
if(!PEAR::isError($mailResult)){ $m++; } else { $n++; }
}
}
/* Relax........ */
echo "Records transfered: " . $m . "<br/>";
echo "Records failed to transfer: " . $n . "<br/>";
Nightmare Episode 1 (FOLLOW UP)
SPF fix (zone file setting, required)
- Go to all SPF testing sites, and check what there wizard saying
Fix PTR (zone file setting, required)
Dkim proxy (zone file setting, required)
Prepare two version Plain text and Html
Check message headers from working emails that arrives without any problem to your inbox like (Google/Yahoo and others top companies), and compare that towards yours
Do not trust Microsoft Outlook 2010 or Old version, because in junk filter (high) its also written similar, it may not be a spam that must be a business issue, to make us stupid. And put us in nightmare to solve those issues.
If you don't agree in those TOP reasons, please advise and bit it, this is what i learned and trying to share, because its very annoying as a developer, if you don't have any answer for this RUBISH EROR, caused by Microsoft Outlook 2010.
First of all its Microsoft itself. To really overcome with this issue you can take action such as:
MailChimp: very nice, after pulling all my hair out why it does not work, i found that they got some nice templates with special secret inside, but any way, i just customized it, and it works, i can hit straight crap Outlook express "Inbox" even its high spam filtered.