Situation
I have a script that is downloading emails from a Gmail account, tweaking the content, and re-sending out the emails.
Problem
Whenever I create an email with an embedded image, Gmail displays the plain text version of the email and the embedded image appears like a regular attachment.
Tested
If I use a different client, the image displays properly. If I forward the email from Gmail to a different client, the image displays properly. Multi-part emails that have regular attachments, or that have both plain text and html parts display properly - as long as they don't have an embedded image.
Email format
From what I can see, the format of the email is correct, but I've pasted it below, trimmed for brevity & privacy. The 2 things I notice is that the boundary appears to be properly set, and the img src cid: matches the Content-ID of the image.
MIME-Version: 1.0
Content-Type: multipart/related;
boundary="_=_swift_1575407655_756d311b6808cc9e07d75ccca0ed9b6c_=_"
--_=_swift_1575407655_756d311b6808cc9e07d75ccca0ed9b6c_=_
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
This email has been sent to a Mailing List. You can approve or reject it a=
t [URL here]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
[image: noice.gif]
-----------------------
[Signature here]
--_=_swift_1575407655_756d311b6808cc9e07d75ccca0ed9b6c_=_
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable
<p>
This email has been sent to a Mailing List. You can approve or reject =
it at [URL here]</p>
<hr />
<div dir=3D"ltr"><div><img src=3D"cid:7f82a31e4f084e8f0a25edd913ed3aa2#swif=
t.generated" alt=3D"noice.gif" width=3D"474" height=3D"244"><br></div><div>=
<div dir=3D"ltr" class=3D"gmail_signature" data-smartmail=3D"gmail_signatur=
e"><div dir=3D"ltr"><div><div dir=3D"ltr"><div><div dir=3D"ltr"><br><br>---=
--------------------<br>[signature here]<br></div>=
</div></div></div></div></div></div></div>
--_=_swift_1575407655_756d311b6808cc9e07d75ccca0ed9b6c_=_
Content-Type: image/gif; name=noice.gif
Content-Transfer-Encoding: base64
Content-ID: <7f82a31e4f084e8f0a25edd913ed3aa2#swift.generated>
Content-Disposition: inline; filename=noice.gif
R0lGODlh2gH0APcAAAgDBRGJG5ZKGsDGB8lNFJJsGkkIBs+nLgnCM4lPZODnDqdMGo4rCVGIKs5q
[... bunch of base64 encoded stuff]
BFGgAUsAEvjkAlQgq/drOjfkFKdEETNBxl3bpi5lBYEAADs=
--_=_swift_1575407655_756d311b6808cc9e07d75ccca0ed9b6c_=_--
PHP code
Here is the PHP code that generates the Mailer object - which is a wrapper around Swiftmailer, and is used to do the actual sending:
$Mailer = new Mailer($subject_prepend.$this->subject);
// Simply a wrapper. Calls $this->Message->setBody($body,'text/plain');,
// where $this->Message is an instance of Swift_Message
$Mailer->setBody($plaintext_prepend.$this->plaintext);
$html_body = $html_prepend.$this->html;
if(count($this->Attachments)){
foreach($this->Attachments as $Attachment){
if($Attachment->isEmbedded()){
$image = \Swift_Image::fromPath($Attachment->getPath())->setDisposition('inline');
$cid = $Mailer->Message->embed($image);
//$cid = $Mailer->embedPath($Attachment->getPath());
$html_body = str_replace('cid:'.$Attachment->cid, $cid, $html_body);
}
else{
// calls $this->Message->attach(\Swift_Attachment::fromPath($path));
$Mailer->addAttachmentPath($Attachment->getPath());
}
}
}
// calls $this->Message->addPart($body,'text/html');
$Mailer->addHTMLBody($html_body);
The commented out line is how I was originally embedding the image, but it had the same result.
-
Is this some Gmail magic that's failing me, or is the email misconfigured somehow?
Edit
I managed to get the email sending properly with PHPMailer. The only difference I can see is that PHPMailer starts with:
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="b1_6hukH7nTGJu6fpr5tpXob5uQE7wXivW0oMppPNbwOi4"
Content-Transfer-Encoding: 8bit
where Swiftmailer starts with
MIME-Version: 1.0
Content-Type: multipart/related; boundary="_=_swift_1575416351_99d22ee774049152f712bc5ae65340fb_=_"
ie: PHPMailer uses multipart/alternative rather than multipart/related, and sets Content-Transfer-Encoding.
Also, all textual parts of SwiftMailer's email was `Content-Transfer-Encoding: quoted-printable' whereas PHPMailer didn't set that header.
Related
I stuck in a problem using 1C-Bitrix framework with PHPMailer. The problem connected with the email body.
1C-Bitrix framework prepares body depending on options enabled. For example, if I turn on the option "Create text vesion of html-email" the body will look like this:
---------alt8045b59706
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is my email
---------alt8045b59706
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<h1> This is my email </h1>
---------alt8045b59706--
If I the email template will have an attached txt file, the body will look like this:
---------mix4215b5973f
Content-Type: multipart/alternative; boundary="-------alt3795b5973f"
---------alt3795b5973f
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is my email
---------alt3795b5973f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<h1> This is my email </h1>
---------alt3795b5973f--
---------mix4215b5973f
Content-Type: text/plain; name="=?UTF-8?B?dGVzdC50eHQ=?="
Content-Transfer-Encoding: base64
Content-ID: <427605>
dGVzdCB0ZXh0Cg==
---------mix4215b5973f--
And, finally, the standard email body will look like this:
<h1> This is my email </h1>
I can't just feed such email body to PHPMailer. It doesn't work correctly. I tried msgHtml() - also doesn't work.
But standard php mail() func works well with such email body.
I found that in PHPMailer I need to set Body and AltBody separately. But then, what is the best way for me to parse such email body.
Maybe somebody knows a tool for it?
Or PHPMailer has a built in methods for it?
Maybe I need to just manually set correct "Content-Type" header (framework tells me correct Content-Type)
Thanks, in advance.
You don't need to think about those things - PHPMailer does it for you. This is all you need to do to make that structure:
$mail->isHTML();
$mail->Body = '<h1> This is my email </h1>';
$mail->AltBody = 'This is my email';
$mail->addAttachment('path/to/file.pdf');
Also, the MIME structure in the example you gave for the message body with an attachment is incorrect, so I wouldn't expect it to work in any context.
I have a need for everyone in my organization to send emails to everyone else in the group.
As there are hundreds of members, and the membership changes often, it is not practical to use the traditional CPanel email forwarding method. So I thought I would pipe the email to a php script, get all the members’ email addresses from the database (checking to make sure the original sender was also in the database) and send on the email to all members using PHPMailer.
I parsed the header in the PHP script to get the From, Subject (adding these of course to PHPMailer), Content-Type, and boundary. Then I collected the actual email message in a variable $message including the lines that say (in this case)
“This is a multi-part message in MIME format.
--------------3D4FAACFC2C069EFCDAE6DC6, etc. (This is of course in text format.)
Just before the PHPMailer Send command, I included:
$mail -> IsHTML(false);
// (I also tried not including this command at all – no change)
$mail->Body =$message;
$mail->addCustomHeader("Content-Type", $content_type . " boundary=" . $boundary);
$content_type and $boundary are the variables I parsed from the original header
As this is still in development, I sent the email to my address only. It was received and displayed properly (both the plain and html as usual), but was marked as Spam – the received Header had the Subject already marked as Spam so I assume PHPMailer did it.
I noticed on the received Header that my custom header appeared correctly:
Content-Type: multipart/alternative; boundary="------------3D4FAACFC2C069EFCDAE6DC6"
The received header also had another Content-Type: text/plain; charset=iso-8859-1 after the above which I assume PHPMailer added. Maybe the two Content-Types is what triggered the Spam tag. I then tried adding $mail->header_remove ('Content-Type'); after the Body call and before addCustomHeader, but the additional Content-Type: text/plain; charset=iso-8859-1 was still in the received header and it was still marked as Spam.
I am using PHPMailer version 5.2.22, and using
$mail->IsSMTP();
, $mail->SMTPAuth = true;
$mail->SMTPSecure = 'ssl';
I can’t continue to unsuccessfully experiment forever as I am afraid sending lots of Spam emails will get me in trouble, so I am hoping someone can tell what I am doing wrong, or even if my overall strategy is flawed. I wish also there was a way to get the header that PHPMailer is going to use before it actually sends out the mail.
Note: my organization is a charitable group with little money, so we can't afford paid SMTP's. I've tried using the free versions of some on the market (not for the above project) but given you are using a shared IP with many others using the free service you often get emails kicked back because others sharing your IP have been Spam tagged
Thanks
This is the entire header (I deleted some of the content just to keep this note a bit brief) that I received to my personal email (b...#....com) from my "forward email" script which uses everybody#....org as the originating address. You can see the Content_Type I added to PHPMailer via $mail->addCustomHeader("Content-Type", $content_type . " boundary=" . $boundary);(which is the multipart.. line) and the one PHPMailer itself added (text/plain...). The email was received fine and displayed properly except for the Spam added to the Subject line:
From - Sat Mar 25 12:51:13 2017
STUFF
Return-Path: <everybody#....org>
Received: from dnvrco-pub-iedge-vip.email.rr.com ([107.14.70.244])
by dnvrco-fep06.email.rr.com
(InterMail vM.8.04.03.24 201-2389-100-172-20151028) with ESMTP
id <20170325165112.EUNA23395.dnvrco-fep06.email.rr.com#dnvrco-pub-iedge-vip.email.rr.com>
for <bmadder#...>; Sat, 25 Mar 2017 16:51:12 +0000
Return-Path: <everybody#....org>
Received: from [173.205.126.142] ...
Received: from ecbiz194.inmotionhosting.com .....
Date: Sat, 25 Mar 2017 12:51:01 -0400
To: b...#....com
From: everybody#....org
Message-ID: ...
Content-Type: multipart/alternative; boundary="------------3D4FAACFC2C069EFCDAE6DC6"
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
X-OutGoing-Spam-Status: No, score=-1.0
X-AntiAbuse:...
X-Get-Message-Sender-Via: ecbiz194.inmotionhosting.com: authenticated_id: everybody#....org
X-Authenticated-Sender: ecbiz194.inmotionhosting.com: everybody#....org
X-Source:
X-Source-Args:
X-Source-Dir:
X-Authority-Analysis: v=2.1 cv=Od5ldUnY c=1 sm=1 tr=0 p=tHMjoff1TzQA:10 a=BPsZ5WN3F+ptBTNoNLYonA==:117 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=9+rZDBEiDlHhcck0kWbJtElFXBc=:19 a=6Iz7jQTuP9IA:10 a=FqPqrT7mAAAA:8 a=wuaQj91YKeLcW_I7NZUA:9 a=FtJ_xtNkBE-qfxEx:21 a=wPNLvfGTeEIA:10 a=yozH4VhRfl4A:10 a=M3AHoUkWFckA:10 a=fZGknuNN1LOydenUCIb6:22
X-Cloudmark-Score: 100
X-RR-Connecting-IP: 107.14.64.106:25
Subject: SPAM: Lots of work today
X-Brightmail-Tracker: AAAAARZYL6Q=
X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrDqMTGxcIABLocC65FGFx/aGGx78B3FgdGj+Mv3jMFMEZx+OWXKAQXJOYmcGT07L7AVsBQAaIaGBlWMSqUlBYbF2cUJxYVF6RWGJjrpacW6xVX5ibmlaQm6yXn525ihJq+g3H7RZlTjJJS4ry3512LEBIoBpqYUQpUVxRfVJqTWvyKUZyDUUmYNxcky5OZV1KcmQ6TkeBgUhLhNdl4JUKIt7gkESEl1cDY81CZ25t3k/zUd21bd90/typmy6NtErw+Xs/YlXtk7atb4j4+/t6yoHDeJ3uN/kP1P7LrIiY5fFipZfynvvPJzbNfz943kPtyweqk3Tn/vpOfGIosVIpPxHht7j+Rl24XEH2vJa1o/q3fJRonvyxi6D4x60xlW8M/o0oLBlvjw4672ZjKQg2UWIozEg21mIuKEwGcu2V6TwEAAA==
This is a multi-part message in MIME format.
--------------3D4FAACFC2C069EFCDAE6DC6
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
This is the text message
--------------3D4FAACFC2C069EFCDAE6DC6
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 8bit
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p>This is the text message <br>
</p>
</body>
</html>
--------------3D4FAACFC2C069EFCDAE6DC6--
I now have the solution. Rather than using the line of $mail->addCustomHeader("Content-Type", $content_type . " boundary=" . $boundary);, I appended the variable $boundary to the variable $content_type and used $mail->ContentType = $content_type; My mail forward script now works perfectly with the Spam label no longer an issue. The header that is sent to the final recipients no longer has duplicate Content-Types listed in the MIME part
App::uses('CakeEmail', 'Network/Email');
$Email = new CakeEmail();
$Email->to($emailContentArray['To']);
$Email->from(array($emailContentArray['From'] => Configure::read('FROM_NAME')));
$Email->subject($emailContentArray['Subject']);
$Email->emailFormat('both');
$response=$Email->send($emailContentArray['Body']);
if we check the resulting email it looks like:-
Content-Type: multipart/mixed; boundary="782f009f669cbcf2faafff59fe0eeb5d"
Content-Transfer-Encoding: 8bit
X-Identified-User: {:test25.xyzzzz.com:testttt.com} {sentby:program running on server}
--782f009f669cbcf2faafff59fe0eeb5d
Content-Type: multipart/alternative; boundary="alt-782f009f669cbcf2faafff59fe0eeb5d"
--alt-782f009f669cbcf2faafff59fe0eeb5d
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
<div>​<BR>Hi<BR><BR>Soon you will reach the action limit. To keep yourself updated please pay the payment.<BR><BR> Happy to have you<BR><BR>Thanks,<BR>Apps Team<BR>​</div>
--alt-782f009f669cbcf2faafff59fe0eeb5d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<div>​<BR>Hi<BR><BR>Soon you will reach the action limit. To keep yourself updated please pay the payment.<BR><BR> Happy to have you<BR><BR>Thanks,<BR>Apps Team<BR>​</div>
In text/plain the email should not show the html tags - how can I get both html and plain text to be sent correctly?
Encode the content and the subject in base64:
"=?utf-8?b?".base64_encode($s)."?=";
And before sending the emails don't forget to set the header:
'Content-Transfer-Encoding: base64';
If I'm not wrong you can make to set header: $Email->setHeader('X-Content-Transfer-Encoding', 'base64');
You can take a look at Cakephp sending UTF-8 Emails and lineLength
And at http://book.cakephp.org/2.0/en/core-utility-libraries/email.html
I am sending some emails with phpmailer with the regular example on their website.
the email is sent, and it arrives perfectly to the sent address.
after the mail is sent, I am saving the email to my sent items folder with imap_append, using the info of this answer Sent mails with phpmailer don't go to "Sent" IMAP folder
and in third place, I am creating a custom made webmail which reads my imap folders.
the problem is that I can't get the html body of the email sent correctly.
When I open the mail on sent items on thunderbird, or my phone, the body is shown perfectly.
but when I try to get the html body with php_imap functions I can't make it!!.
I created an isolated file to fetch the body of the msg like this:
$body = imap_fetchbody($conn,3392,1,FT_UID);
that returns this:
--b1_9db4e4310d1b141cbec79dd7de22f70b Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit á é à ñ Ñ REMOVED CONTENT --------------------- klfasjdkl adj skldj klfdj akfdsj lkfdasjfkl dasjf --b1_9db4e4310d1b141cbec79dd7de22f70b Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit á é à ñ Ñ
REMOVED CONTENT
---------------------
klfasjdkl adj skldj klfdj akfdsj lkfdasjfkl dasjf --b1_9db4e4310d1b141cbec79dd7de22f70b--
If I try
$body = imap_fetchbody($conn,3392,1.2,FT_UID);
don't get anything
If I try
$body = imap_fetchbody($conn,3392,2,FT_UID);
don't get anything, it seems that PHPMailer creating the emailbody in a way that imap_fetchbody can't handle?
thank you
I have a small "problem" with Zend_Mail_Storage_Imap and MultiPart Mails.
ContentType: multipart/alternative;
boundary=f46d043bd88a9f5d9004c87d2ad3
Part 1 has the Text of the Message, but with headers inside the content, so when i try
$part->getContent();
--f46d043bd88a9f5d9004c87d2ad3 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hallo
is the result, how to extract the header information now?
Instead of:
$part->getContent();
do:
$part->getHeader();
to get Headers or if you want ONLY content then:
try:
while ($part->isMultipart()) {
$part = $message->getPart(1);
}
or
$message = $mail->getMessage($messageNum);
for content without body.
If issue persists, check your mail on mail client's like Gmail. Sometimes, we add header information twice (accidentally) whilst sending the mail.
Hope this helps :)