Du coup j'ai supprimé mon précédent message dans le forum BugTracking. (la version est désormais obsolète)
Ci-dessous une version très grandement modifié de Mail2Ticket qui permet de récupérer les pièces jointes et les images (et les affiche convenablement sur le ticket dans Gestsup.
Fonctionne avec les emails envoyés depuis Outlook et désormais Gmail.
L'encodage des noms de PJ semble différent suivant le mailbrowser qui envoie le mail.
Pour les images j'ai modifié le code et désormais tout devrait bien s'afficher quelque soit l'expéditeur.
Sinon, pour le fonctionnement, on trouve l'email en question sur le serveur, on parcours l'ensemble des parts de l'email de façon récursive, et suivant le type de la parts on la traite différemment (corps du texte / pièce jointes / images).
Exemple d'un email récupéré avec ce code :
Code : Tout sélectionner
<?php
//error_reporting(E_ALL);
$count=0;
//connexion script with database parameters
require "connect.php";
//define current time
$datetime = date("Y-m-d H:i:s");
//load parameters table
$qparameters = mysql_query("SELECT * FROM `tparameters`");
$rparameters= mysql_fetch_array($qparameters);
//hostname building
$hostname = '{'.$rparameters['imap_server'].':'.$rparameters['imap_port'].'}'.$rparameters['imap_inbox'].'';
//connect to inbox
//-----Default Case
//$inbox = imap_open($hostname,$rparameters['imap_user'],$rparameters['imap_password']) or die('Impossible de se connecter au serveur de Messagerie: ' . imap_last_error());
//-----Exchange2010
$inbox = imap_open('{'.$rparameters['imap_server'].':'.$rparameters['imap_port'].'/imap/novalidate-cert}'.$rparameters['imap_inbox'].'', $rparameters['imap_user'], $rparameters['imap_password'],NULL,1,array('DISABLE_AUTHENTICATOR'=>'GSSAPI')) or die('Impossible de se connecter au serveur de Messagerie: ' . imap_last_error());
//display header
echo'
<html lang="fr">
<head>
<meta charset="UTF-8" />
</head>
';
if($inbox)
{
//grab mail
echo "<u></u>Connexion à la boite au lettre en cours: <font color=green>ok</font><br /><br />";
$emails = imap_search($inbox,'ALL');
//if emails are returned
if($emails) {
//for every email...
foreach($emails as $email_number) {
//get next new ticket id
$query = mysql_query("SELECT MAX(id) FROM tincidents");
$row=mysql_fetch_array($query);
$tid=$row[0]+1;
//get information specific to this email
$overview = imap_fetch_overview($inbox, $email_number, 0);
$seen=$overview[0]->seen;
//if message is not read
if ($seen==0)
//if($email_number==12)
{
$count=$count+1;
//get mail data
$emailMessage = new EmailMessage($inbox, $email_number,"upload/".$tid."/");
$emailMessage->fetch();
//$tes = $emailMessage->bodyHTML;
//echo "$tes";
//$te = $emailMessage->bodyPlain;
//echo "$te";
if($emailMessage->EmailStructure == "parts"){
// IN CASE OF PARTS EMAIL STRUCT
$message = $emailMessage->bodyHTML;
// Bug Correction 05/11 : getting the code inside the body balise only
// Otherwise the message displayed on the wysywig editor is updated to text
$bodyPos=0;
$bodyPos=strpos($message,"<body");
$message=substr($message,$bodyPos);
$bodyPos=strpos($message,">");
$message=substr($message,$bodyPos+1);
$bodyPos=strpos($message,"</body>");
$message=substr($message,0,$bodyPos-1);
//special char convert
$message=quoted_printable_decode($message);
$message = str_replace("'","''",$message);
}
else{
// IN CASE OF SIMPLE EMAIL STRUCT
$message = $emailMessage->bodyPlain;
$message = base64_decode($message);
}
//Escape special char to SQL query
//$message=mysql_real_escape_string($message); //no more needed
$header = imap_headerinfo($inbox, $email_number);
$subject = $overview[0] -> subject;
$from = $header->from[0]->mailbox . "@" . $header->from[0]->host;
$subject=mb_decode_mimeheader($subject);
$subject = str_replace('_', ' ', $subject);
$subject=mysql_real_escape_string($subject);
//find gestsup userid from mail address
$query= mysql_query("SELECT id FROM `tusers` where mail='$from' ");
$row=mysql_fetch_array($query);
if($row[0])
{
$user_id=$row[0];
} else {
$user_id='';
$message='De '.$from.':\n'.$message;
}
//attachment for the query
$aCount=$emailMessage->attachmentsCount;
$aArray=$emailMessage->attachments;
$fields="";
$values="";
for($z = 0; $z < $aCount; $z++) {
$y=$z+1;
$fields .= "img".$y.",";
$values .= "'".$aArray[$z]['filename']."',";
}
//echo "START";
//echo "$message";
//echo "END";
// create ticket
$query= "INSERT INTO tincidents
(user,technician,title,description,date_create,".$fields."techread,state,criticality,disable,place)
VALUES ('$user_id','0','$subject','$message','$datetime',".$values."'0','5','4','0','1')";
$exec = mysql_query($query) or die('Erreur SQL !<br />'.mysql_error());
//echo $query;
echo " > Import du message $count: $subject: <font color=green>ok</font><br />";
}
}
}
imap_close($inbox);
echo "<br />Total: Récupération de $count messages depuis <b>$rparameters[imap_server]</b> depuis le port <b>$rparameters[imap_port]</b><br />";
} else {
echo "Erreur de connexion IMAP";
}
echo '</html>';
exit;
class EmailMessage {
protected $connection;
protected $messageNumber;
protected $imagePathFolder;
public $bodyHTML = '';
public $bodyPlain = '';
public $EmailStructure = ''; //simple or parts
public $attachments=array();
public $attachmentsCount=0;
public $imageNumber=0;
public $imgsrc = array(); //array because you can have more than 1 image
public function __construct($connection, $messageNumber, $imagePathFolder) {
$this->connection = $connection;
$this->messageNumber = $messageNumber;
$this->imagePathFolder = $imagePathFolder; //exemple "upload/image/"
//folder creation if it don't exist
if (!file_exists($imagePathFolder)) {
mkdir($imagePathFolder, 0777);
}
}
public function fetch() {
//look for all the email parts and extract the body
$structure = @imap_fetchstructure($this->connection, $this->messageNumber);
if(!$structure) {
return false;
}
else {
if(property_exists ( $structure , "parts" )){
//Parts exist
$this->EmailStructure = "parts";
$this->RecursiveFetch($structure->parts);
//For debug HELP ONLY
//$this->printobject($structure);
}
else {
//parts do not exist (it means no attachments & simple body)
// simply check the body
$this->EmailStructure = "simple";
$this->bodyPlain = imap_body($this->connection, $this->messageNumber);
//For debug HELP ONLY
//$this->printobject($structure);
}
return true;
}
}
// PRINTARRAY & PRINT OBJECT are used for debug only
//use $this->printobject($structure);
//to print the structure of an email
public function printarray($array){
while(list($key,$value) = each($array)){
if(is_array($value)){
echo $key."(array):<blockquote>";
$this->printarray($value);
echo "</blockquote>";
}elseif(is_object($value)){
echo $key."(object):<blockquote>";
$this->printobject($value);
echo "</blockquote>";
}else{
echo $key."==>".$value."<br />";
}
}
}
public function printobject($obj){
$array = get_object_vars($obj);
$this->printarray($array);
}
public function RecursiveFetch($messageParts, $prefix = '', $index = 1, $fullPrefix = true) {
foreach($messageParts as $part) {
$partNumber = $prefix.$index;
switch($part->type) {
//===================== CHECKING FOR THE BODY MESSAGE ====================
//Please check imap_fetchstructure on php.net for more details about type
case 0:
if($part->subtype == 'PLAIN') {
//------- Case PLAIN TEXT --------
$txt = $this->getPart($partNumber, $part->encoding);
$this->bodyPlain .= $txt;
}
else {
//------- Case HTML --------
$txt = $this->getPart($partNumber, $part->encoding);
//update all img src since the one we get means nothing (and target nothing)
//the src is updated here and the image download/save below ()check type==5 for image)
//the src for exchange is still starting by cid:imagexxx where xxx is the image number
//this is followed by an id.
//the objective is to update the src to target the image we will download
$pos= strpos($txt,"cid:");
$remainHTML = $txt; //the remaining html code we have to check
$imagecount=0;
while ($pos){
$this->imgsrc[$imagecount] = array(
'src' => '',
'filename' => '');
$remainHTML = substr($remainHTML,$pos);
$temp = str_pad($imagecount, 3, "0", STR_PAD_LEFT);
$this->imgsrc[$imagecount]['filename'] = "TemporaryImageName".$temp; //substr($remainHTML,4,strpos($remainHTML,'"')-4); //isolating the image name
$this->imgsrc[$imagecount]['src'] = substr($remainHTML,0,strpos($remainHTML,'"')); //isolating the image src from the actual html body
$imagecount = $imagecount+1;
$remainHTML = substr($remainHTML,1);
$pos = strpos($remainHTML,"cid:");
}
//replacing all img src by the temporaryimagename
//you can change the $imagePathFolder property
for($i = 0; $i < $imagecount; $i++) {
$txt = str_replace($this->imgsrc[$i]['src'],$this->imagePathFolder.$this->imgsrc[$i]['filename'],$txt);
}
$this->bodyHTML .= $txt;
}
break;
//MULTIPART - depend of the mail structure, it vary depending on the library used (apple, gmail, exchange ? ?)
//sometimes the body can be found on part 1. sometimes it is on a subpart 1.1 - 1.2 etc...
//that's why we need the recursive function.
case 1:
if(isset($part->parts)) {
if($fullPrefix) {
$this->RecursiveFetch($part->parts, $prefix.$index.'.');
}
else {
$this->RecursiveFetch($part->parts, $prefix);
}
}
break;
//===================== ATTACHED EMAIL =========================
case 2:
//probably used when an email is attached to the email you are fetching.
break;
//===================== SAVE IMAGES OR ATTACHMENTS TO THE SPECIFIED DIRECTORY ====================
default:
//All attachments
// 3 : application
// 4 : audio
// 5 : image (attached or paste)
// 6 : video
// 7 : other
$filename="";
$filename = $this->getFilenameFromPart($part);
//echo "$filename";
//If the part is an attachment and not a paste image
if (isset($part->disposition)){
if ($part->disposition == 'attachment'){
$this->attachments[$this->attachmentsCount] = array(
'filename' => $filename);
$this->attachmentsCount = $this->attachmentsCount+1;
}
else {
//if the part is a paste image
$this->bodyHTML = str_replace($this->imgsrc[$this->imageNumber]['filename'],$filename,$this->bodyHTML);
$this->imageNumber = $this->imageNumber+1;
}
}
//saving all images / attachments
$attachment = $this->getPart($partNumber, $part->encoding);
//echo "$this->imagePathFolder";
//echo "$filename";
//echo "$this->imagePathFolder" + "$filename";
file_put_contents($this->imagePathFolder.$filename,$attachment);
break;
}
$index++;
}
}
function getPart($partNumber, $encoding) {
$data = imap_fetchbody($this->connection, $this->messageNumber, $partNumber);
switch($encoding) {
case 0: return $data; // 7BIT
case 1: return $data; // 8BIT
case 2: return $data; // BINARY
case 3: return base64_decode($data); // BASE64
case 4: return quoted_printable_decode($data); // QUOTED_PRINTABLE
case 5: return $data; // OTHER
}
}
function getFilenameFromPart($part) {
$filename = '';
if($part->ifdparameters) {
foreach($part->dparameters as $object) {
if(strtolower($object->attribute) == 'filename') {
$filename = $object->value;
//decodage UTF8- useful for gmail emails
//echo "$filename";
$filename = imap_utf8($filename);
$filename = utf8_decode($filename);
$filename = str_replace("?","",$filename);
}
}
}
if(!$filename && $part->ifparameters) {
foreach($part->parameters as $object) {
if(strtolower($object->attribute) == 'name') {
$filename = $object->value;
//decodage UTF8- useful for gmail emails
$filename = imap_utf8($filename);
$filename = utf8_decode($filename);
$filename = str_replace("?","",$filename);
}
}
}
return $filename;
}
}
?>
@+++