Création de fonctionnalités de messagerie avancées avec IMAP et PHP

Ce que vous allez créer

Dans ce tutoriel, je vais vous présenter quelques exemples concrets montrant comment utiliser PHP et IMAP pour créer de nouvelles fonctionnalités permettant de gérer votre messagerie. Des fonctionnalités que les grands fournisseurs de services de messagerie n'ont pas conçues pour nous..

Mon intérêt pour cela a commencé en 2010 lorsque j'ai écrit Douze idées Gmail pour révolutionner la messagerie électronique (encore une fois), mais la plupart des idées que je souhaitais sont restées hors de portée. Pour aussi important que l'email est, l'innovation de l'email en tant qu'application a été assez lente.

Nous nous noyons dans des e-mails et la gestion de nos boîtes de réception reste un lourd fardeau. Les services de courrier et les clients ont très peu fait pour nous aider avec cela. La plupart des courriels que nous recevons sont envoyés par des machines et non par des personnes, et pourtant nous sommes ceux qui doivent les traiter individuellement.. 

L'analyse de mon propre courrier électronique a montré que je recevais un courrier électronique de plus de 230 expéditeurs automatisés, beaucoup moins de personnes réelles. J'en avais assez de construire des filtres dans Gmail et de remplir une myriade de formulaires de désabonnement. Je voulais avoir plus de contrôle sur la gestion de mon courrier électronique et me simplifier la vie.

Enfin, cette année, j'ai décidé de créer les fonctionnalités dont j'avais besoin. Le résultat est Simplify Email (SE), une petite application Web que vous pouvez héberger vous-même et offrant une variété de nouvelles fonctionnalités de messagerie intéressantes que vous pouvez consulter sur le site Web du projet..

La chose la plus intéressante à propos de SE est qu’il s’agit d’une plate-forme de lecture, d’analyse, de routage et de gestion de votre courrier électronique. Les possibilités sont nombreuses. Simplify Email est essentiellement un terrain de jeu programmable pour "pirater" votre propre courrier électronique..

Je vais vous expliquer le code de trois exemples de SE utilisant PHP, IMAP et MySQL pour travailler avec le courrier électronique:

  1. Vérification de votre boîte de réception et filtrage des messages
  2. Mise en œuvre d'un défi de liste blanche pour les expéditeurs inconnus
  3. Signaler un courrier électronique sans réponse

Ce tutoriel vous donnera certainement une longueur d'avance sur l'écriture de code IMAP en PHP. Mais vous pouvez également travailler directement avec la base de code Simplify Email. Vous pouvez acheter le code pour aussi peu que 10 $, et il existe une version plus ancienne à code source ouvert (qui manque de certaines des fonctionnalités que nous décrivons ci-dessous). Les guides d'installation sont fournis pour les configurations Linux typiques. J'offre également des images pré-installées chez Digital Ocean pour 25 $ ainsi qu'un service de voiturier. SE est écrit en PHP, dans le framework Yii. 

Notez que vous ne pourrez pas accéder à la plupart des serveurs de messagerie via votre ordinateur de développement local à moins de compiler une bibliothèque IMAP sécurisée pour PHP. C'est l'une des raisons pour lesquelles j'encourage les gens à utiliser Simplify Email dans des gouttelettes chez Digital Ocean. Il existe également quelques astuces pour que la sécurité des comptes Google vous permette d'entrer via IMAP..

Travailler avec IMAP

Comment simplifier les emails

Avec SE, vous pouvez continuer à utiliser le client de messagerie de votre choix sur le Web et sur vos appareils mobiles. Vous n'avez pas à changer les applications ou les habitudes personnelles. SE accède à vos comptes de messagerie en coulisse via IMAP; En tant qu'assistant personnel intelligent, SE traite à l'avance votre courrier électronique, en déplaçant les messages aux endroits appropriés en fonction de tout ce que vous leur avez dit..

Lorsqu'un message parvient d'un expéditeur familier, SE le déplace dans le dossier que vous avez spécifié. Quand on arrive d'un expéditeur inconnu pour la première fois, il le déplace dans le dossier de révision. 

Toutes les deux heures (ou à une fréquence que vous aurez choisie), SE vous enverra un résumé de l’emplacement où vos messages ont été déplacés et des messages en cours de révision. Remarque: des liens pour les expéditeurs de formation sont inclus dans le dossier de révision, ce qui facilite la formation de SE au fil du temps..

A tout moment, vous pouvez parcourir votre dossier de révision. Vous n'avez pas à attendre que le résumé soit arrivé. Mais l’avantage de SE, c’est que vous n’avez plus à parcourir vos dossiers; vous pouvez simplement lire votre résumé pour avoir une vue de l'email que vous avez reçu et former de nouveaux expéditeurs.

1. Vérification de votre boîte de réception et filtrage des messages

SE utilise plusieurs tâches périodiques pour fonctionner en arrière-plan sur votre serveur. Chacun s'appelle de DaemonController.php.

La première, processInbox, est appelé fréquemment et doit fonctionner rapidement. Son travail consiste à filtrer le courrier électronique et à le déplacer le plus rapidement possible hors de la boîte de réception et dans le dossier de triage, appelé dossier de filtrage.. 

La deuxième, processFiltering, nécessite davantage de processus et effectue des opérations plus approfondies sur le courrier électronique, finissant par déplacer les messages vers leur destination finale.

La méthode ProcessInbox

Les appels de tâches cron processInbox régulièrement:

public function actionInbox () // déplace les messages de la boîte de réception vers @filtering // s'exécute fréquemment $ r = new Remote (); $ r-> processInbox (); 

Pour chaque compte, nous déchiffrons vos informations d'identification de messagerie, puis utilisons imap_open pour créer un flux IMAP dans votre dossier de boîte de réception:

fonction publique open ($ account_id, $ mailbox = ", $ options = NULL) // ouvre le dossier d'un compte IMAP $ account = Account :: model () -> findByPk ($ account_id); $ this-> nom_hôte = $ compte-> adresse; if (! stristr ($ this-> nom_hôte, '')) $ ceci-> nom_hôte = ''. $ this-> nom_hôte. ''; $ cred = Account :: model () -> getCredentials ($ account-> cred); if ($ account-> fournisseur == Compte :: PROVIDER_ICLOUD) // icloud n'accepte que le nom de la boîte aux lettres, par exemple stevejobs contre [email protected] $ temp = explode (' @ ', $ cred [0]); $ cred [0] = $ temp [0]; $ this-> stream = imap_open ($ this-> nom_hôte. $ mailbox, $ cred [0], $ cred [1 ], $ options, 1) ou die ('Connexion au serveur de messagerie impossible - account_id:'. $ account_id. ". print_r (imap_errors ()));  

Dans processInbox, nous utilisons les fonctions de bibliothèque PHP imap_search et imap_fetch_overview pour récupérer un tableau de messages:

// lookup folder_id de la boîte aux lettres de ce compte $ folder_id = Folder :: model () -> lookup ($ account_id, $ this-> path_inbox); $ this-> open ($ account_id, $ this-> path_inbox); $ cnt = 0; $ message_limit = 50; // pause après n messages pour éviter l'expiration du délai echo 'Tri depuis:' .date ("j F Y, $ tstamp); // format de date imap_search 30 novembre 2013 $ recent_messages = @imap_search ($ this-> flux, 'SINCE "' .date (" j F Y ", $ tstamp)." ", SE_UID); if ($ recent_messages === false) continue; // à faire - continuer dans le compte suivant $ result = imap_fetch_overview ($ this-> stream, implode (',', array_slice ($ recent_messages, 0, $ message_limit)), FT_UID); 

Ensuite, nous traitons le tableau de messages dans la boîte de réception:

foreach ($ result as $ item) if (! $ this-> checkExecutionTime ($ time_start)) break; // récupère l'en-tête et le flux de msg $ msg = $ this-> parseHeader ($ item); 

Voici une version adaptée du code d'analyse d'en-tête IMAP accessible au public, qui rassemble les informations supplémentaires dont SE a besoin pour diverses tâches. Fondamentalement, il utilise imap_rfc822_parse_adrlist pour déterminer les informations du destinataire, l'identifiant du message, l'objet et l'horodatage (ou les informations de l'expéditeur lors de l'analyse du dossier envoyé):

 fonction publique parseHeader ($ header) // analyse l'objet en-tête renvoyé par imap_fetch_overview if (! isset ($ header-> from)) return false;  else $ from_arr = imap_rfc822_parse_adrlist ($ header-> à partir de, 'gmail.com'); $ fi = $ from_arr [0]; $ msg = array ("uid" => (isset ($ header-> uid))? $ header-> uid: 0, "personal" => (isset ($ fi-> personnel))? @ imap_utf8 ($ fi -> personal): "", "email" => (isset ($ fi-> boîte aux lettres) && isset ($ fi-> hôte))? $ fi-> boîte aux lettres. "@". $ fi-> hôte: " "," mailbox "=> (isset ($ fi-> mailbox))? $ fi-> mailbox:" "," host "=> (isset ($ fi-> host))? $ fi-> host:" "," subject "=> (isset ($ header-> subject))? @ imap_utf8 ($ header-> subject):" "," message_id "=> (isset ($ header-> message_id))? $ header- > message_id: "", "in_reply_to" => (isset ($ header-> in_reply_to))? $ header-> in_reply_to: "", "udate" => (isset ($ header-> udate))? $ header- > udate: 0, "date_str" => (isset ($ header-> date))? $ header-> date: ""); // gère les opérations d'extraction avec les en-têtes uid et rfc if ($ msg ['udate'] == 0 && isset ($ header-> date)) $ msg ['udate'] = strtotime ($ header-> date);  $ msg ['rx_email'] = "; $ msg ['rx_personal'] ="; $ msg ['rx_mailbox'] = "; $ msg ['rx_host'] ="; if (isset ($ header-> to)) $ to_arr = imap_rfc822_parse_adrlist ($ header-> to, 'gmail.com'); $ to_info = $ to_arr [0]; if (isset ($ to_info-> mailbox) && isset ($ to_info-> hôte)) $ msg ['rx_email'] = $ to_info-> boîte aux lettres. '@'. $ to_info-> hôte;  if (isset ($ to_info-> personnel)) $ msg ['rx_personal'] = $ to_info-> personnel; if (isset ($ to_info-> mailbox)) $ msg ['rx_mailbox'] = $ to_info-> mailbox; if (isset ($ to_info-> hôte)) $ msg ['hôte_rx'] = $ to_info-> hôte;  return $ msg; 

Nous créons des enregistrements pour l'expéditeur et l'enveloppe du message dans notre base de données:

 // ignore les messages système si ($ msg ['email'] == $ system_email) continue; // si udate est trop ancien, ignorez msg if (time () - $ msg ['udate']> $ this-> scan_seconds) continue; // ignore les msg // action par défaut $ action = self :: ACTION_MOVE_FILTERED; $ isNew = $ s-> isNew ($ account_id, $ msg ["email"]); // cherche l'expéditeur, s'il est nouveau, créez-le $ sender_id = $ s-> add ($ user_id, $ account_id, $ msg ["personal"], $ msg ["mailbox"], $ msg ["host"], 0); $ sender = Sender :: model () -> findByPk ($ sender_id); // crée un message dans la base de données si nécessaire $ message_id = $ m-> add ($ user_id, $ account_id, 0, $ sender_id, $ msg ['message_id'], $ msg ['subject'], $ msg ['udate '], $ msg [' in_reply_to ']); $ message = Message :: model () -> findByPk ($ message_id); 

Si l'expéditeur est nouveau pour nous (inconnu), nous vous enverrons un e-mail de défi de liste blanche (nous parlerons plus en détail des défis de liste blanche dans la section suivante ci-dessous):

if ($ isNew) $ this-> challengeSender ($ user_id, $ account_id, $ sender, $ message); 

Ensuite, nous déterminons si l'utilisateur a peut-être fait glisser un message d'un autre dossier dans la boîte de réception afin de le former par glisser-déposer. Si tel est le cas, nous configurons la formation de cet expéditeur dans la boîte de réception. En d'autres termes, la prochaine fois, nous voudrions simplement router les messages de cet expéditeur vers la boîte de réception:

 if ($ message ['status'] == Message :: STATUS_FILTERED || $ message ['status'] == Message :: STATUS_REVIEW || ($ message ['status'] == Message :: STATUS_TRAINED && $ message [ 'folder_id'] <> $ folder_id) || ($ message ['status'] == Message :: STATUS_ROUTED && message $ '[folder_id'] <> $ folder_id)) // alors c'est une formation $ action = self :: ACTION_TRAIN_INBOX;  else if (($ message ['status'] == Message :: STATUS_TRAINED || $ message ['status'] == Message :: STATUS_ROUTED) && $ message ['folder_id'] == $ folder_id) // s'il est déjà formé ou s'il est déjà acheminé vers la boîte de réception, ignorez-le $ action = self :: ACTION_SKIP; echo 'Formé précédemment, sauter'; lb (); continuer;  

Sinon, nous nous préparerons à déplacer le message dans le dossier Filtrage pour traitement ultérieur. Premièrement, nous pouvons envoyer des notifications au téléphone de l'utilisateur s'il existe une correspondance expéditeur ou mot clé pour les notifications (et que ce ne sont pas des heures creuses):

 if ($ action == self :: ACTION_MOVE_FILTERED) $ cnt + = 1; if ($ sender-> exclude_quiet_hours == Sender :: EQH_YES ou! $ this-> isQuietHours ($ user_id)) // envoie des notifications de smartphone basées sur l'expéditeur if ($ sender-> alert == Sender :: ALERT_YES) $ this-> notify ($ expéditeur, $ message, Monitor :: NOTIFY_SENDER);  // envoie des notifications basées sur des mots clés if (AlertKeyword :: model () -> scan ($ msg)) $ this-> notify ($ expéditeur, $ message, Monitor :: NOTIFY_KEYWORD);  // déplacer msg imap vers + Filtrage echo 'Déplacement vers + Filtrage'; lb (); // $ result = @imap_mail_move ($ this-> flux, $ msg ['uid'], $ this-> path_filtering, CP_UID); $ result = $ this-> messageMoveHandler ($ msg ['uid'], $ this-> path_filtering, false); if ($ result) echo 'déplacé
'; $ m-> setStatus ($ message_id, Message :: STATUS_FILTERED);

Si le message a été glissé dans la boîte de réception, nous mettrons à jour nos paramètres de formation:

else if ($ action == self :: ACTION_TRAIN_INBOX) // définit l'expéditeur folder_id dans la boîte de réception echo 'Train to Inbox'; lb (); $ m-> setStatus ($ message_id, Message :: STATUS_TRAINED); // ne forme l'expéditeur que lorsque le message est plus récent que le dernier paramètre if ($ msg ['udate']> = $ sender ['last_trained']) $ s-> setFolder ($ sender_id, $ folder_id); 

La méthode ProcessFiltering

La méthode de traitement secondaire s'appelle processFiltering, aussi dans DaemonController.php. Les aspects les plus longs du déplacement des messages dans les dossiers appropriés sont les suivants:

fonction publique actionIndex () // traite les messages de @Filter dans les dossiers appropriés $ r = new Remote (); $ r-> processFiltering (); // Enregistrement de l'horodatage de cronjob pour la surveillance $ file = file_put_contents ('./ protected / runtime / cronstamp.txt', time (), FILE_USE_INCLUDE_PATH);  

Cette méthode ouvre votre compte de messagerie pour rechercher des messages récents et collecter des données à leur sujet. Il utilise aussi imap_search, imap_fetch_overview et parseHeader:

$ tstamp = time () - (7 * 24 * 60 * 60); // Il y a 7 jours $ recent_messages. @Imap_search ($ this-> stream, 'SINCE "' .date (" j F Y ", $ tstamp). '"', SE_UID); if ($ recent_messages === false) continue; // à faire - continuer dans le compte suivant $ result = imap_fetch_overview ($ this-> stream, implode (',', array_slice ($ recent_messages, 0, $ message_limit)), FT_UID); foreach ($ result en $ item) $ cnt + = 1; if (! $ this-> checkExecutionTime ($ time_start)) break; // récupère l'en-tête et le flux de msg $ msg = $ this-> parseHeader ($ item); 

La boucle de traitement principale pour chaque message du dossier de filtrage est assez détaillée. Nous examinons d’abord l’adresse du destinataire, car SE permet aux utilisateurs de former des dossiers en fonction de l’adresse du destinataire, par exemple. les messages destinés au domaine happyvegetarian.com sont placés dans le dossier veggie:

 // Définit l'action par défaut à déplacer dans le dossier de révision $ action = self :: ACTION_MOVE_REVIEW; $ destination_folder = 0; // recherche et création du destinataire $ recipient_id = $ r-> add ($ user_id, $ account_id, $ msg ['rx_email'], 0); $ routeByRx = $ this-> routeByRecipient ($ recipient_id); if ($ routeByRx! == false) $ action = $ routeByRx-> action; $ destination_folder = $ routeByRx-> destination_folder;  

Ensuite, nous recherchons l'expéditeur et créons un nouvel enregistrement dans la base de données (si nécessaire). Si la formation existe pour l'expéditeur, nous pouvons définir le dossier de destination:

 // cherche l'expéditeur, s'il est nouveau, créez-le $ sender_id = $ s-> add ($ user_id, $ account_id, $ msg ["personal"], $ msg ["mailbox"], $ msg ["host"], 0); $ sender = Sender :: model () -> findByPk ($ sender_id); // si la destination de l'expéditeur est connue, route vers le dossier si ($ destination_folder == 0 && $ sender ['folder_id']> 0) $ action = self :: ACTION_ROUTE_FOLDER; $ destination_folder = $ sender ['folder_id'];  

Si un (nouvel) expéditeur non formé s'est vérifié via un défi de la liste blanche (dont nous discuterons dans la section suivante ci-dessous), nous acheminerons ce message dans la boîte de réception:

// La liste blanche des expéditeurs vérifiés va dans la boîte de réception si ($ sender-> is_verified == 1 && $ sender ['folder_id'] == 0 && UserSetting :: model () -> useWhitelisting ($ user_id)) // place le message dans boîte de réception $ action = self :: ACTION_ROUTE_FOLDER; $ destination_folder = Folder :: model () -> lookup ($ account_id, $ this-> path_inbox); 

Ensuite, nous créons une entrée de message dans la base de données avec les informations d'enveloppe concernant ce message:

 // créer un message dans db $ message = Message :: model () -> findByAttributes (array ('message_id' => $ msg ['message_id'])); if (! empty ($ message)) // message existe déjà, $ message_id = $ message-> id;  else $ message_id = $ m-> add ($ user_id, $ account_id, 0, $ sender_id, $ msg ['message_id'], $ msg ['subject'], $ msg ['udate'], $ msg [ 'en réponse à']);  

S'il provient d'un expéditeur inconnu et non vérifié, nous pouvons déplacer le message dans le dossier de révision. Le dossier de révision contient tous les messages d'expéditeurs que nous ne reconnaissons pas..

Si le message provient d'un expéditeur connu et que nous avons une destination en tête, nous pouvons le déplacer tant que les heures ne sont pas calmes (et que la fonction Ne pas déranger est désactivée):

 if ($ recipient_id! == false) $ m-> setRecipient ($ message_id, $ recipient_id); if ($ action == self :: ACTION_MOVE_REVIEW) echo 'Déplacement vers + Filtrage / Révision'; lb (); // $ result = @imap_mail_move ($ this-> flux, $ msg ['uid'], $ this-> path_review, CP_UID); $ result = $ this-> messageMoveHandler ($ msg ['uid'], $ this-> path_review, false); if ($ result) echo 'déplacé
'; $ m-> setStatus ($ message_id, Message :: STATUS_REVIEW); else if ($ action == self :: ACTION_ROUTE_FOLDER || $ action == self :: ACTION_ROUTE_FOLDER_BY_RX) // recherche le nom du dossier par folder_id $ folder = Folder :: model () -> findByPk ($ destination_folder); // si la boîte de réception et les heures creuses ne sont pas programmées, ne route pas maintenant si (strtolower ($ folder ['nom']]) == 'boîte de réception' et $ sender-> exclude_quiet_hours == Sender :: EQH_NO et $ this-> isQuietHours ( $ user_id)) continue; echo 'Moving to'. $ folder ['name']; lb (); $ mark_read = Folder :: model () -> isMarkRead ($ folder ['mark_read'])) || Sender :: model () -> isMarkRead ($ sender ['mark_read']); // $ result = @imap_mail_move ($ ce-> flux, $ msg ['uid'], $ dossier ['nom'], CP_UID); $ result = $ this-> messageMoveHandler ($ msg ['uid'], $ dossier ['nom'], $ mark_read); if ($ result) echo 'déplacé
'; $ m-> setStatus ($ message_id, Message :: STATUS_ROUTED); $ m-> setFolder ($ message_id, $ destination_folder);

Pendant les heures creuses, les messages sont principalement conservés dans le dossier de filtrage..

Toutes les deux heures, un processus différent créera le résumé du message en utilisant les enregistrements de la table des messages pour déterminer les messages récemment reçus et filtrés et leur mode de routage..

2. Implémentation d'un défi de liste blanche pour des expéditeurs inconnus

L’objectif du défi de la liste blanche est de conserver tout message provenant d’un expéditeur inconnu, par exemple. éventuellement un bot marketing ou un spammeur, hors de votre boîte de réception. SE place le courrier provenant d'expéditeurs inconnus dans le dossier de révision. Cependant, si vous activez la liste blanche, nous envoyons un courrier électronique de défi qui permet à l'expéditeur de vérifier qu'il est humain. S'ils répondent, nous déplacerons le message dans votre boîte de réception. Si l'email s'avère indésirable, vous pouvez zapper le message depuis le résumé ou le faire glisser dans le dossier de votre choix..

L'utilisateur peut activer et désactiver les listes blanches dans les paramètres:

Pour mettre en place la liste blanche, nous envoyons des défis par courrier électronique chaque fois que le courrier arrive d'un nouvel expéditeur:

if ($ isNew) $ this-> challengeSender ($ user_id, $ account_id, $ sender, $ message); 

ChallengeSender envoie un lien codé à l'utilisateur pour qu'il clique dessus. Nous avons également quelques protections pour nous assurer de ne pas nous piéger dans une boucle de messagerie avec un message d'absence du bureau:

 fonction publique challengeSender ($ user_id, $ account_id, $ sender, $ message) // liste blanche défi email $ yg = new Yiigun (); $ ac = Account :: model () -> findByPk ($ account_id); if (! empty ($ ac ['challenge_name'])) $ $ = $ ac ['challenge_name']. ' mg_domain. '>'; else $ from = 'Filtrer mg_domain. '>'; $ cred = Account :: model () -> getCredentials ($ ac-> cred); $ account_email = $ cred [0]; non défini ($ cred); // sécurité: ne vérifie aucun email récent si ($ sender-> last_emailed> (time () - (48 * 60 * 60))) return false; if ($ sender-> isBot ($ sender ['email'])) // à faire - peut également définir cette personne en bloc par défaut return false;  $ link = Yii :: app () -> getBaseUrl (true). "/ sender / verify / s /".$ sender-> id." / m /".$ message-> id. '/ u /' . $ message-> udate; $ subject = 'Veuillez vérifier le message que vous avez envoyé'. $ account_email; $ body = "

salut,

J'essaie de réduire le courrier électronique non sollicité. Pourriez-vous s'il vous plaît vérifier votre adresse e-mail en cliquant sur le lien ci-dessous:
'. $ link.'

En vérifiant votre adresse e-mail, votre message sera rapidement envoyé dans ma boîte de réception. Merci pour votre aide!

'; $ yg-> send_html_message ($ from, $ sender ['email'], $ subject, $ body); // met à jour last_emailed $ sender-> touchLastEmailed ($ sender-> id);

Ensuite, si le destinataire clique sur le lien codé, nous les vérifions dans la base de données. Le contrôleur d’expéditeur traite ces demandes et vérifie leur validité:

 fonction publique actionVerify ($ s = 0, $ m = 0, $ u = 0) // vérifie que l'URL msg sécurisée de Digest est valide, connectez-vous à l'utilisateur, affichez msg $ ID_expéditeur_S = $ s; $ message_id = $ m; $ udate = $ u; $ msg = Message :: model () -> findByPk ($ message_id); if (! empty ($ msg) && $ msg-> sender_id == $ sender_id && $ msg-> udate == $ udate) $ result = 'Merci pour votre aide. Je vais répondre à votre courriel dès que possible. '; $ a = new Advanced (); $ a-> verifySender ($ msg-> account_id, $ sender_id);  else $ result = 'Désolé, nous n'avons pas pu vérifier votre adresse email.';  $ this-> render ('verify', array ('result' => $ result,)); 

Cela indique à nos boucles de traitement de déplacer ce message et les messages futurs de cet expéditeur vers la boîte de réception..

3. Signaler un courrier électronique sans réponse

Parfois, il est utile de voir un résumé des messages que vous avez envoyés mais auxquels vous n’avez pas répondu. Pour les identifier, Simplify Email surveille les messages envoyés sans réponse..

Chaque message que nous recevons contient un identifiant unique, appelé message_id (partie de la spécification IMAP). Cela ressemble souvent à ceci:

ID du message: 

En outre, lorsque des messages sont envoyés en réponse à d’autres messages, ils ont une en réponse à champ qui renvoie à l'original ID du message.

Donc, nous utilisons une requête SQL pour trouver tous les messages reçus qui n'ont pas de message de réponse correspondant référençant leur ID du message. Pour cela, nous utilisons un LEFT OUTER JOIN où il n'y a pas en réponse à id:

fonction publique getUnanswered ($ account_id, $ mode = 0, $ range_days = 7) if ($ mode == 0) $ subject_compare = 'not'; sinon $ subject_compare = "; $ query = Yii :: app () -> db-> createCommand (" SELECT fi_sent_message.id, fi_sent_message.recipient_id en tant que sender_id, fi_sent_message LEFT OUTER JOIN fi_message ON fi_message.in_reply_to = fi_sent_message.message_ess WHERE fi_sent_message.account_id = ". Account_id." ). "et fi_sent_message.subject". $ subject_compare. "comme 'Re:%' ORDER BY fi_sent_message.udate DESC") -> queryAll (); return $ query;

Nous utilisons le $ subject_compare mode pour différencier nos messages envoyés qui n'ont pas reçu de réponse de nos réponses envoyées à un fil de discussion qui n'a pas été répondu. Voici le rapport de message sans réponse dans votre compte:

SE propose également ces informations sous forme de résumé facultatif, appelé résumé de courrier électronique sans réponse. Vous pouvez le recevoir tous les jours, tous les deux ou trois semaines.

Nous utilisons également une tabulation SQL similaire avec Google Charts pour fournir des rapports sur la fréquence à laquelle certaines personnes vous envoient des courriers électroniques:

 fonction publique reportInbound ($ account_id, $ range = 30, $ limit = 100) $ result = Yii :: app () -> db-> createCommand ('SELECT fi_sender.personal, fi_sender.email, count (sender_id) as cnt DE fi_message LEFT JOIN fi_sender ON fi_sender.id = fi_message.sender_id WHERE fi_sender.account_id =: account_id ET fi_message.created_at> DATE_SUB (NOW (), INTERVAL: jour) GROUP BY sender_id ORDER BY cnt descript LIMIT:) bindValue ('range', $ range) -> bindValue ('account_id', $ account_id) -> bindValue ('limit', $ limit) -> queryAll (); return $ result;  

J'écrirai plus sur Google Charts for Tuts + bientôt. 

Prochaines étapes

J'espère que vous avez trouvé Simplify Email assez intriguant pour vous initier à la programmation PHP IMAP. Il y a tellement de fonctionnalités intéressantes que vous pouvez créer sans que les grands fournisseurs de messagerie ne fassent rien de nouveau.

Si vous avez des questions ou des corrections, merci de les poster dans les commentaires. Si vous souhaitez suivre mes futurs tutoriels et autres séries de Tuts +, suivez s'il vous plaît @reifman ou visitez la page de mon auteur. Vous pouvez aussi me contacter ici.

Liens connexes

Voici quelques liens supplémentaires qui pourraient vous être utiles:

  • Simplifier le courrier électronique
  • Introduction à la simplification du courrier électronique (vidéo)
  • Douze idées Gmail pour révolutionner le courrier électronique (encore) 
  • Couverture de Simplify Email dans BoingBoing ici et ici
  • Référence PHP IMAP
  • Introduction au framework Yii (Tuts +)