web-dev-qa-db-fra.com

Envoyer PHP courrier HTML avec pièces jointes

J'ai un problème: jusqu'à aujourd'hui, j'envoyais des mails HTML avec PHP en utilisant un en-tête qui contient

Content-type: text/html;

Maintenant, j'ai ajouté des fonctionnalités pour ajouter des pièces jointes. Pour cela, j'ai dû changer cette ligne en

Content-Type: multipart/mixed;

Maintenant avec multipart/mixed, le reste du courrier, donc le texte normal, est affiché comme texte/simple. Comment puis-je réaliser que les pièces jointes fonctionnent et que le texte du courrier est toujours HTML?

12
Florian Müller

Pour envoyer un e-mail avec pièce jointe, nous devons utiliser le type MIME en plusieurs parties/mixte qui spécifie que les types mixtes seront inclus dans l'e-mail. De plus, nous voulons utiliser le type MIME en plusieurs parties/alternatif pour envoyer à la fois du texte brut et la version HTML de l'e-mail.

<?php 
//define the receiver of the email 
$to = '[email protected]'; 
//define the subject of the email 
$subject = 'Test email with attachment'; 
//create a boundary string. It must be unique 
//so we use the MD5 algorithm to generate a random hash 
$random_hash = md5(date('r', time())); 
//define the headers we want passed. Note that they are separated with \r\n 
$headers = "From: [email protected]\r\nReply-To: [email protected]"; 
//add boundary string and mime type specification 
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\""; 
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents('attachment.Zip'))); 
//define the body of the message. 
ob_start(); //Turn on output buffering 
?> 
--PHP-mixed-<?php echo $random_hash; ?>  
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>" 

--PHP-alt-<?php echo $random_hash; ?>  
Content-Type: text/plain; charset="iso-8859-1" 
Content-Transfer-Encoding: 7bit

Hello World!!! 
This is simple text email message. 

--PHP-alt-<?php echo $random_hash; ?>  
Content-Type: text/html; charset="iso-8859-1" 
Content-Transfer-Encoding: 7bit

<h2>Hello World!</h2> 
<p>This is something with <b>HTML</b> formatting.</p> 

--PHP-alt-<?php echo $random_hash; ?>-- 

--PHP-mixed-<?php echo $random_hash; ?>  
Content-Type: application/Zip; name="attachment.Zip"  
Content-Transfer-Encoding: base64  
Content-Disposition: attachment  

<?php echo $attachment; ?> 
--PHP-mixed-<?php echo $random_hash; ?>-- 

<?php 
//copy current buffer contents into $message variable and delete current output buffer 
$message = ob_get_clean(); 
//send the email 
$mail_sent = @mail( $to, $subject, $message, $headers ); 
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed" 
echo $mail_sent ? "Mail sent" : "Mail failed"; 
?>

Comme vous pouvez le voir, l'envoi d'un e-mail avec pièce jointe est facile à réaliser. Dans l'exemple précédent, nous avons un type MIME à plusieurs parties/mixte, et à l'intérieur, nous avons un type MIME à plusieurs parties/alternatif qui spécifie deux versions de l'e-mail. Pour inclure une pièce jointe à notre message, nous lisons les données du fichier spécifié dans une chaîne, les codons en base64, les divisons en petits morceaux pour nous assurer qu'elles correspondent aux spécifications MIME, puis les incluons en tant que pièces jointes.

10
Sanjay Prajapati

J'ai essayé la réponse 1 pendant quelques heures sans succès. J'ai trouvé une solution ici: http://www.finalwebsites.com/forums/topic/php-e-mail-attachment-script

Fonctionne comme un charme - moins de 5 min! Vous voudrez peut-être changer (comme je l'ai fait), le premier type de contenu de text/plain en text/html.

Voici ma version légèrement modifiée pour gérer plusieurs pièces jointes:

function mail_attachment($files, $path, $mailto, $from_mail, $from_name, $replyto, $subject, $message) {
$uid = md5(uniqid(time()));

$header = "From: ".$from_name." <".$from_mail.">\r\n";
$header .= "Reply-To: ".$replyto."\r\n";
$header .= "MIME-Version: 1.0\r\n";
$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
$header .= "This is a multi-part message in MIME format.\r\n";
$header .= "--".$uid."\r\n";
$header .= "Content-type:text/html; charset=iso-8859-1\r\n";
$header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$header .= $message."\r\n\r\n";

    foreach ($files as $filename) { 

        $file = $path.$filename;

        $file_size = filesize($file);
        $handle = fopen($file, "r");
        $content = fread($handle, $file_size);
        fclose($handle);
        $content = chunk_split(base64_encode($content));

        $header .= "--".$uid."\r\n";
        $header .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n"; // use different content types here
        $header .= "Content-Transfer-Encoding: base64\r\n";
        $header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
        $header .= $content."\r\n\r\n";
    }

$header .= "--".$uid."--";
return mail($mailto, $subject, "", $header);
}
26
Brian

SWIFTMAIL en php fonctionne gr8 pour la pièce jointe avec les mails.

Téléchargez swiftmailer à partir d'ici http://swiftmailer.org/

Regardez le code simple ci-dessous

INCLURE LE FICHIER

require_once('path/to/swiftMailer/lib/Swift_required.php');

CRÉER DES TRANSPORTS

//FOR SMTP
// Create the Transport
$transport = Swift_SmtpTransport::newInstance('smtp.googlemail.com', 465, 'ssl')
    ->setUsername('[email protected]')
    ->setPassword('gmailpassword');

OR

//FOR NORMAL MAIL
$transport = Swift_MailTransport::newInstance();

OBJET MAILER

// Create the Mailer using your created Transport
$mailer = Swift_Mailer::newInstance($transport);

CRÉER UN OBJET DE MESSAGE

$message = Swift_Message::newInstance($subject)
    ->setFrom(array($from => $from))
    ->setTo($to)
    ->setBody($body);
$message->attach(Swift_Attachment::fromPath($filepath));

ENVOYER LE MESSAGE

$result = $mailer->send($message);
3
Rayiez

Si vous voulez vraiment apprendre à formater un message Internet, vous devez vous référer à sa demande de commentaires (alias RFC). Celui qui définit les "Extensions de messagerie Internet polyvalentes - Format des corps de message Internet" est RFC2045 publié en novembre 1996.

Le format est en quelque sorte très strict et doit être suivi tel quel.

Fondamentalement, le message contient un en-tête et le corps. L'en-tête définit le type du message, la façon dont il est formaté, quelques autres champs qui diffèrent d'un type à l'autre.

Le corps est formé de différentes entités. Une entité peut être par exemple juste un texte en clair comme "Hello there!" mais peut aussi être une image, un attachement, peu importe.

[~ # ~] note [~ # ~] Dans les exemples suivants, tout ce qui est placé entre crochets (par exemple {bonjour}) doit être remplacé par votre vrai valeur. Toute nouvelle ligne est en réalité CRLF (ie. ASCII 13 + ASCII 10). Où vous voyez deux CRLF s'y tenir. Ce serait le pire moment pour montrez à quel point vous êtes créatif.

Fondamentalement, pour un e-mail contenant des pièces jointes, l'en-tête doit ressembler à ceci:

MIME-Version: 1.0
To: {email@domain}
Subject: {email-subject}
X-Priority: {2 (High)}
Content-Type: multipart/mixed; boundary="{mixed-boudary}"

Dans l'exemple ci-dessus, le {mixed-boudary} peut avoir n'importe quelle valeur de hachage unique, comme 000008050800060107020705. Les autres sont explicites.

Maintenant, chaque fois que nous voulons ajouter une nouvelle entité au message (comme le corps du message, une image, une pièce jointe), nous devons dire à l'agent de messagerie que une nouvelle section arrive, c'est-à-dire. pour préfixer cette entité avec la valeur {mixed-bound}. Nous appelons cela "ouvrir la frontière". Notez qu'en ouvrant une frontière, nous n'insérons pas cette frontière comme cela a été défini initialement, nous utilisons 2 autres signes moins devant, comme - {mixed-boudary}. Lorsque nous fermons une frontière, nous procédons de la même manière, sauf que nous devons utiliser d'autres signes 2 moins à la fin, comme - {mixed-boudary} -

--{mixed-boudary}
the entity content
--{mixed-boudary}--

Parce que l'agent de messagerie doit comprendre quel type a le contenu de notre nouvelle entité insérée, nous devons le déclarer juste après l'ouverture de la frontière. La déclaration est juste un en-tête qui contient uniquement les paramètres/valeurs compatibles avec l'entité.

Pour un contenu de corps HTML, mon en-tête d'entité ressemblerait à:

Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

de sorte que le corps entier (enfermé dans des limites) ressemblera finalement à:

--{mixed-boudary}
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<html>
<head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head>
<body bgcolor="#FFFFFF" text="#000000">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel 
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus 
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat 
accumsan, consectetur ex et, rhoncus risus.
</body>
</html>

Si une autre entité doit être insérée, nous procédons exactement comme ci-dessus. Lorsqu'il n'y a plus de données à ajouter au message, nous fermons la frontière mixte, c'est-à-dire. CRLF + - {bouddhiste mixte} -.

Si, pour une raison quelconque, une entité doit être insérée avec une représentation alternative (par exemple, un corps de message est inséré à la fois au format texte brut et également au format HTML), le contenu de l'entité doit être déclaré avec le type de contenu multipart/alternative (bien que l'en-tête global multipart/mixed reste toujours!). Chaque représentation alternative sera délimitée par cette nouvelle frontière.

Un exemple complet ci-dessous:

MIME-Version: 1.0
To: {email@domain}
Subject: {email-subject}
X-Priority: {2 (High)}
Content-Type: multipart/mixed; boundary="{mixed-boudary}"

--{mixed-boudary}
Content-Type: multipart/alternative; boundary="{alternative-boudary}"

--{alternative-boudary}
Content-Type: text/plain; charset=utf-8;
Content-Transfer-Encoding: 7bit

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel 
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus 
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat 
accumsan, consectetur ex et, rhoncus risus.

--{alternative-boudary}
Content-Type: text/html; charset=utf-8;
Content-Transfer-Encoding: 7bit

<html>
<head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head>
<body bgcolor="#FFFFFF" text="#000000">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel 
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus 
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat 
accumsan, consectetur ex et, rhoncus risus.
</body>
</html>

--{alternative-boudary}--

--{mixed-boudary}
Content-Type: application/pdf; name="myfile.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="myfile.pdf"

JVBERi0xLjINOCAwIG9iag08PCAvTGVuZ3RoIDkgMCBSIC9GaWx0ZXIgL0ZsYXRlRGVjb2Rl
ID4+DXN0cmVhbQ1oQ51bbY/cNg7+BfsfhAUO11w3riW/B7gPaZEAAdpcm06RL8EBzoyn68uM
vZ3xZLv//khKsuUxNaMNiiabpUg+pKiHsmxJEcN/UsgiilP4ab2/+XF1I81vszSqclHIOEpj
sdrf/PC2EFVUpmK1vXkZxVKs1uJlJJVYPYrvPra7XVvvxYdIrE7rL83hhVj97+bNyjUoFam7
FnOB+tubGI3FZEkwmhpKXpVRnqJi0PCyjBJ1DjyOYqWBxxXp/1h3X+ov9abZt434pV0feoG/
ars/xU/9/qEZmm7diJ+abmgOr0TGeFNFEuXx5M4B95Idns/QAaJMI1IpKeXi9+ZhaPafm4NQ
cRwzNpK0iirlRvisRBZpVJa+PP51091kkjBWBXrJxUuZRjIXh0Z8FN3MnB5X5st5Kay9355n

--{mixed-boudary}--

[~ # ~] astuces [~ # ~]

Utilisez votre client de messagerie préféré (le mien est Thunderbird) et envoyez-vous un message en texte brut uniquement, un HTML uniquement, un mixte, puis chacun des précédents mais avec une pièce jointe jointe. Lorsque vous recevez le message, étudiez simplement sa source (Affichage -> Source du message).

@Edit: une étude de cas très bien documentée + PHP peut être trouvé sur ici

1
Eugen Mihailescu