Randomly broken html content

Swift Mailer is a fantastic library for sending email with php. Discuss this library or ask any questions about it here.

Moderators: Chris Corbyn, General Moderators

Post Reply
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Randomly broken html content

Post by dantahoua »

I have a weird problem with swiftmailer. When I batchsend a mail, sometimes, it seems that the decorator plugin screw up the html content. The code stop with : swift-11337913384653146cdd13e9.42341019_
The alt/text part of the mail is correct, seems logical cause this part do not go in the decorator.
I found that if I send exactly the same content a second time to my recipient list, the mail is good... Maybe a cache problem, it's weird. Here is the code, if someone has an idea...

Code: Select all

require_once('../Class/Courriel.php');
	require_once('../Class/CourrielCollection.php');
	require_once('../Class/Template.php');
	require_once('../Class/LongDate.php');
	//Instanciation de l'objet swift pour envoyer les mails
	require_once('../Class/Swift.php');
	require_once('../Class/Swift/Plugin/Decorator.php');
	require_once('../Class/Swift/Plugin/AntiFlood.php');
	//require_once('../Class/Swift/Plugin/Throttler.php');
	//$throttler =& new Swift_Plugin_Throttler();
	//$throttler->setEmailsPerMinute(120); //Max of 2 email every 1 seconds
	require_once ('../Class/Swift/Plugin/BandwidthMonitor.php');
	//require_once "../Class/Swift/Plugin/VerboseSending.php";
	
	if ($objconf->GetSmtp_mode() == 1)
	{
		require_once('../Class/Swift/Connection/SMTP.php');
		$swift =& new Swift(new Swift_Connection_SMTP($objconf->GetSmtp_host(),$objconf->GetSmtp_port()));
	}
	else
	{
		require_once('../Class/Swift/Connection/NativeMail.php');
		$swift =& new Swift(new Swift_Connection_NativeMail());
	}
	
	//Création du plugin de monitorage de bande passante
	$bandwidth =& new Swift_Plugin_BandwidthMonitor();
	
	//Activation des logs pour afficher les problèmes sur certaines adresses.
	$swift->log->enable();
	
	//Création du message
	$message =& new Swift_Message(htmlspecialchars($_POST['sujet']));
	
	//Création des parties du message multipart
	//Partie text ->
	$text_part = str_replace('</p>','\n',$_POST['fr_texte']);
	$text_part = strip_tags($text_part);
	
	//Création de la date au format long...
	$date = new LongDate(date("Y-m-d"));

	//Partie html ->
	//Remplissage du template
	$template = new template('Modules/Mail/Templates/'.$objconf->GetTemplate());
	
	//Travail sur les décorations header et footer
	if ($objconf->GetDecorationStatut())
	{
		if ($_POST['imageselect'] != '')
		{
			$arimg = explode(';',$_POST['imageselect']);
			$headerimg = $arimg[0];
			$footerimg = $arimg[1];
			$header = $objconf->GetBase_url().'/uploads/mail/headfoot/'.$headerimg;
			$footer = $objconf->GetBase_url().'/uploads/mail/headfoot/'.$footerimg;
		}
	}
	//Récupére le texte du footer sélectionné
	if ($objconf->GetFooterTextstatut())
	{
		$pied = new MailFooter($_POST['footerselect']);
		$footer_texte_fr = $pied->GetTexte('fr');	
	}
	
	//Création du nom de fichier en prévision de l'archivage
	$nomfichier = 'b'.date("dmYGis").'.html';
	
	//Remplace titre, header, footer et texte dans le template
	$template->assign('TITRE',$_POST['sujet']);
	$template->assign('DATE',$date->GetLongDate());
	$template->assign('TEXTE',$_POST['fr_texte']);
	if ($objconf->GetDecorationStatut())
	{
		$template->assign('IMG_HEADER',$header);
		$template->assign('IMG_FOOTER',$footer);
	}
	if ($objconf->GetFooterTextstatut())$template->assign('FOOTER',$footer_texte_fr);
	$template->assign('FICHIER','Si vous avez des probl&egrave;mes pour visualiser ce message, <a href="'.$objconf->GetBase_url().'/uploads/mail/arch/'.$nomfichier.'">cliquez ici</a> pour le voir.');
	
	//On récupère le template dans une variable
	$html_part = $template->__toString();
	
	//Enregistre le contenu dans un fichier html pour visualisation future
	if($fp = fopen('../uploads/mail/arch/'.$nomfichier,"w"))
	{ /* ouverture du fichier en écriture */
		fputs($fp, "\n"); // on va a la ligne
		fputs($fp, "$html_part"); // on écrit le nom et email dans le fichier
		fclose($fp);
	}
	else
	{ // L'ouverture a échouée
		echo "Ouverture du fichier impossible";
		exit();
	}
		
	//On attache les partie texte brut et html au message
	$message->attach(new Swift_Message_Part($text_part));
	$message->attach(new Swift_Message_Part($html_part, "text/html"));
	
	//Création de la liste d'envoie
	$recipients =& new Swift_RecipientList();
	
	//Création d'un array pour remplacer COURRIEL et URL_UNSUSCRIBE dans le corps
	$arReplace = array();
	
	//Gestion du champ courriel
	if ($_POST['courriel'] != '')
	{
		$arcourriel = explode(';',$_POST['courriel']);
		for ($i=0;$i<sizeof($arcourriel);$i++)
		{
			$recipients->addTo($arcourriel[$i]);
			$arTemp = array($arcourriel[$i] => array("{COURRIEL}" => $arcourriel[$i]));
			$arReplace = array_merge($arReplace,$arTemp);
		}
	}
	
	//Gestion des groupes
	if (isset($_POST['groupes'])){$check = $check + 1;}
	
	//Gestion des langues
	if (isset($_POST['langues'])){$check = $check + 2;}
	
	//Récupération des courriel en fonction de ce qui est coché et ajout à la liste d'envoie
	switch ($check) {
		case 1:$arobjcourriel = CourrielCollection::GetAllbyGroupe($_POST['groupes']);break;
		case 2:$arobjcourriel = CourrielCollection::GetAllbyLang($_POST['langues']);break;
		case 3:$arobjcourriel = CourrielCollection::GetAllbyGroupeLang($_POST['groupes'],$_POST['langues']);break;
	}
	if (!empty($arobjcourriel))
	{
		foreach ($arobjcourriel as $courriel)
		{
			$recipients->addTo($courriel->GetCourriel(),$courriel->GetPrenom()." ".$courriel->GetNom());
			$arTemp = array($courriel->GetCourriel() => array("{COURRIEL}" => $courriel->GetId()));
			$arReplace = array_merge($arReplace,$arTemp);
		}
	}
	//Ajout d'un return_path
	$message->setReturnPath($objconf->GetReturn_path());
	
	//Plugin antiflood pour eviter le débordement du serveur
	//Reconnect after 100 emails, but wait for 10 seconds first
	$swift->attachPlugin(new Swift_Plugin_AntiFlood(100, 10), "anti-flood");
	
	//Plugin pour la bandepassante
	$swift->attachPlugin($bandwidth, "bwmon");
	
	//Load the plugin with these replacements
	$swift->attachPlugin(new Swift_Plugin_Decorator($arReplace), "decorator");
	
//Envoie des courriels et retour du nombre envoyé
	$number_sent = $swift->batchSend($message, $recipients, new Swift_Address($objconf->GetFrom_email(), $objconf->GetFrom_name()));
	$courriel_erreur = implode(" ,", $swift->log->getFailedRecipients());
	$fr_mess_erreur .= 'Nombre de courriels envoyés : '.$number_sent.'<br/>';
	$fr_mess_erreur .= 'Octets envoyés : ' . $bandwidth->getBytesOut() . '<br />';
    $fr_mess_erreur .= 'Octets reçus : ' . $bandwidth->getBytesIn() . '<br />';
    $swift->log->dump();
	if ($courriel_erreur != ''){$fr_mess_erreur .= 'Courriel qui n\'ont pas fonctionnés'.$courriel_erreur.'<br/>';}
	unset($recipients);unset($arReplace);
Note that the file I created when I send the mail is correct, so the problem really seems to come from the decorator plugin...
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Post by dantahoua »

I forgot:
I use the last Swift version: 3.2.3 for php 4
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

I'm just about to leave the office and cycle home, I'll have a closer look at your code when I get home :)
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Post by dantahoua »

Ok, cool! I'm in front of my computer for a while, so I will check. If you want some informations... I hate random problem... It does it maybe 1 time for 5 times...
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Post by dantahoua »

Hey, I find something... When I use special caractere in the subject, the problem occured. When I remove special caractere in the subject, everything is fine... My webpage is UTF-8, so the form post some UTF-8... The problem, we speak french in Québec and è à ç é are very common...
I tried:

Code: Select all

$message =& new Swift_Message(utf8_decode($_POST['sujet']));
but it changes nothing and my subject become '?'... Weird...
I tried

Code: Select all

$message =& new Swift_Message(htmlentities(utf8_decode($_POST['sujet'])));
But the mailer (thunderbird) do not display the character but: &eacute for é ... And the html is still broken...
Any idea... ?
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Post by dantahoua »

Ok, sorry, I'm on fire!:D
If find that I have to put

Code: Select all

$template->assign('TITRE',htmlentities(utf8_decode($_POST['sujet'])));
It seems that the decore plugin do not like UTF-8... :?

The problem came from that line and not from the line:

Code: Select all

$message =& new Swift_Message($_POST['sujet']);
When I do that it seems to work, even with é è à or ç in the subjet...

But, there is still a small problem: some mailer display correctly the subject, but some other (like hotmail), don't...
With utf8_decode, the subject is '?' and with htmlentities, the mailer display &eacute for é, ...

Any idea to have my subject right everywhere ?
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Post by dantahoua »

Ok I find that in the header of the mailer the line subject is : Subject: =?utf-8?Q?Test_d'accent_transform=E9,_=E9_=E0_=E7?=
UTF-8 appears even if I send the subject with utf8_decode, that's why I get a ?.
Sending the subject UTF-8 seems to be a problem just with hotmail, I tested it with yahoo, gmail, thunderbird, outlook, outlook-express(work 50%), mac mail...
Maybe I should send only iso-8859-1, but I want my application futur proof and all language proof... :?
Maybe all that can help someone with the same problem.
Thanks.
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Post by dantahoua »

Sorry to flood the forum, but just to be clear here are my final question:
-Is there a way to deal with utf-8 content with the plugin decorator ? Cause all my template are UTF-8.


For the header, I will send my mail with

Code: Select all

$message->headers->setCharset("ISO-8859-1");
$message->setSubject(utf8_decode($_POST['sujet']));
because of some company not doing there job (did I say Microsoft?).
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Could you forward the source (in a plain text file) of one of your broken emails to chris@w3style.co.uk please? :)

You could PM it to me here. To my knowledge, UTF-8 should work fne with the decorator. I wondered if there was a mb_str_replace() but there isn't because I think str_replace() is multibyte string safe anyway.

The =?...?....?= syntax in the headers is simply because UTF-8 is not allowed in headers so it gets encoded into a different format. You do need to ensure that if you're using UTF-8 then you have to use UTF-8 everywhere though.
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Post by dantahoua »

I redirected a broken mail to you.
Thanks.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Hi, I got your first email saying that your going to redirect an email to me, but the second email didn't arrive. I'll guess it got stuck in my spam filter due to the message structure issues you're having. If you're able to just put the email source in a text file that would be a lot better thanks :)

EDIT | I just checked my logs and I see it was rejected with a spam score of 2.2 due to various different things:

tests=BAYES_00,FORGED_RCVD_HELO,
HTML_90_100,HTML_IMAGE_ONLY_08,HTML_IMAGE_RATIO_02,HTML_MESSAGE,
HTML_TAG_BALANCE_BODY,MPART_ALT_DIFF_COUNT

Some general advice regarding that breakdown:

FORGED_RCVD_HELO is common and not very serious. It means that reverse DNS found your server to be something other than your domain name.
MPART_ALT_DIFF is likely to do with the issue in the Decorator plugin so ignore that.
HTML_***.... All these are penalizing you for using too much HTML (i.e. mostly images) and also because the HTML has tags which do not pair up (such as <div> foo <div> bar </div> ).

Just some general info for you ;)

Forward your message to me as a plain text file, or PM it to me here. I'm basically just wanting to see what's causing the boundary to appear in the text.
User avatar
dantahoua
Forum Newbie
Posts: 11
Joined: Tue May 22, 2007 11:06 am
Location: Québec / Canada
Contact:

Post by dantahoua »

Thanks for these informations! I send you back the broken message and the full one.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

dantahoua wrote:Thanks for these informations! I send you back the broken message and the full one.
I can confirm I received these. Thank you :)
Post Reply