Bygg avanserte e-postfunksjoner med IMAP og PHP

Hva du skal skape

I denne veiledningen vil jeg gå gjennom noen virkelige eksempler på hvordan du kan bruke PHP og IMAP til å bygge nye funksjoner for å administrere dine e-postfunksjoner som de store e-postleverandørene ikke har bygget for oss.

Min interesse for dette begynte i 2010 da jeg skrev tolv Gmail-ideer for å revolusjonere e-post (igjen), men for det meste de ideene jeg ønsket for, har holdt seg utenfor rekkevidde. For så viktig som e-post er, har innovasjon av e-post som et søknad vært ganske sakte.

Vi drukner i e-post, og det er en tung byrde å administrere innbokser. E-posttjenester og klienter har gjort svært lite for å hjelpe oss med dette. Det meste av e-posten vi mottar, sendes av maskiner, ikke folk, og likevel er vi de som må behandle alt det. 

Analyse av min egen e-post viste at jeg mottok e-post fra mer enn 230 automatiserte sendere, langt færre faktiske personer. Jeg var lei av å konstruere filtre i Gmail og fylle ut et mylder av abonnementskjemaer. Jeg ønsket å ha mer kontroll over å administrere e-posten min og forenkle livet mitt.

Endelig, i det siste året bestemte jeg meg for å bygge de funksjonene jeg trengte. Resultatet er å forenkle e-post (SE), en liten webapp du kan være vert for som tilbyr et utvalg av kule nye e-postfunksjoner som du kan sjekke ut på prosjektets nettside.

Den kuleste tingen om SE er at det er en plattform for lesing, analyse, ruting og styring av din e-post - mulighetene florerer. Forenkle Email er i hovedsak en programmerbar lekeplass for "hacking" din egen e-post.

Jeg går deg gjennom koden på tre eksempler fra SE som bruker PHP, IMAP og MySQL til å jobbe med e-post:

  1. Sjekker innboksen og filtreringsmeldingene
  2. Implementere en Whitelist utfordring til ukjente sendere
  3. Rapporterer ubesvart e-post

Denne opplæringen vil definitivt gi deg en start når du skriver IMAP-koden i PHP. Men du kan også jobbe direkte med koden for forenkle e-post. Du kan kjøpe koden for så lite som $ 10, og det er en eldre åpen kildekodeversjon (som mangler noen av funksjonene vi beskriver nedenfor). Installasjonsveiledninger er gitt for typiske Linux-konfigurasjoner. Jeg tilbyr også forhåndsinstallerte bilder på Digital Ocean for $ 25, samt en håndholdt betjentinstallasjon. SE er skrevet i PHP, i Yii Framework. 

Merk at du ikke vil få tilgang til de fleste e-postservere via din lokale utviklingsmaskin, med mindre du samler et sikkert IMAP-bibliotek for PHP. Dette er en av grunnene til at jeg oppfordrer folk til å kjøre forenkle e-post i dråper ved Digital Ocean. Det er også noen få triks for å få Google-kontosikkerhet til å gi deg inn via IMAP.

Arbeider med IMAP

Hvordan forenkle e-post fungerer

Med SE kan du fortsette å bruke e-postklienten din på både Internett og mobilenheter. Du trenger ikke å endre noen apps eller personlige vaner. SE åpner dine e-postkontoer bak kulissene via IMAP; SE fungerer som en smart personlig assistent, og pre-behandler e-posten din, flytting meldinger til de riktige stedene, basert på alt du har fortalt.

Når en melding kommer fra en kjent sender, flyttes SE til den mappen du har oppgitt. Når en kommer fra en ukjent avsender for første gang, flyttes den til oversiktsmappen. 

Hvert par timer (eller med en frekvens du velger), sender SE deg et sammendrag av hvor det flyttet meldingene dine og hvilke meldinger som er i vurdering. Merk, koblinger til treningsforsendere er inkludert i gjennomgangskatalogen, noe som gjør det ganske enkelt å trene SE over tid.

Du kan når som helst bla gjennom din gjennomgangskatalog - du må ikke vente på å fordøye å ankomme. Men fordelen med SE er at du ikke lenger trenger å bla gjennom mappene dine; Du kan bare lese din fordøyelse for å få en oversikt over e-posten du har mottatt og trene nye sendere.

1. Kontrollere innboks og filtreringsmeldinger

SE bruker flere cron-oppgaver til å fungere i bakgrunnen på serveren din. Hver er kalt fra DaemonController.php.

Den første, processInbox, kalles ofte og trenger å operere raskt - jobben sin er å skjerm e-post og flytte den ut av innboksen så raskt som mulig og inn i triagemappen, kalt filtreringsmappen. 

Den andre, processFiltering, er mer prosessintensiv og utfører dypere operasjoner på e-post, i siste omgang flytte meldinger til deres endelige destinasjon.

ProcessInbox-metoden

Cron oppgavene ringer processInbox jevnlig:

offentlig funksjon actionInbox () // flytter innboks meldinger til @filtering // kjører ofte $ r = ny Remote (); $ R-> processInbox (); 

For hver konto dekrypterer du e-postadressene dine, og bruker imap_open til å opprette en IMAP-strøm i innboksen din:

offentlig funksjon åpen ($ account_id, $ mailbox = ", $ options = NULL) // åpner mappe i en IMAP-konto $ account = Konto :: modell () -> findByPk ($ account_id); $ this-> hostname = $ konto-> adresse, hvis (! stristr ($ dette-> vertsnavn, '')) $ this-> hostname = ''. $ dette-> vertsnavn. ''; $ cred = Konto :: modell -> getCredentials ($ account-> cred); hvis ($ account-> leverandør == Konto :: PROVIDER_ICLOUD) // icloud aksepterer bare navn del av postkasse f.eks stevejobs vs [email protected] $ temp = explode (' @ $, $ cred [0]); $ cred [0] = $ temp [0]; $ this-> stream = imap_open ($ dette-> vertsnavn. $ postkasse, $ cred [0], $ cred [1 ], $ opsjoner, 1) eller dø ('Kan ikke koble til e-postserver - account_id:'. $ account_id. 'print_r (imap_errors ()));  

Innenfor processInbox, vi bruker PHP biblioteksfunksjoner imap_search og imap_fetch_overview for å hente en rekke meldinger:

// lookup folder_id av denne kontoen er INBOX $ folder_id = Mappe :: modell () -> oppslag ($ account_id, $ this-> path_inbox); $ Dette-> open ($ ACCOUNT_ID, $ dette-> path_inbox); $ Cnt = 0; $ message_limit = 50; // bryte etter n meldinger for å hindre timeout echo 'Sorter siden:' .date ("j F Y", $ tstamp); // imap_search datoformat 30. november 2013 $ recent_messages = @imap_search ($ this-> stream, 'SINCE' '.date ("j F Y", $ tstamp).' '', SE_UID); hvis ($ recent_messages === false) fortsett; // å gjøre - fortsett inn i neste konto $ result = imap_fetch_overview ($ this-> stream, implode (',', array_slice ($ recent_messages, 0, $ message_limit)), FT_UID); 

Da behandler vi en rekke meldinger i innboksen:

foreach ($ resultat som $ item) hvis (! $ this-> checkExecutionTime ($ time_start)) pause; // få msg header og stream uid $ msg = $ this-> parseHeader ($ item); 

Her er en tilpasset versjon av offentlig tilgjengelig IMAP-headerparsingskode som samler tilleggsinformasjonen som SE trenger for en rekke oppgaver. I utgangspunktet bruker den imap_rfc822_parse_adrlist for å bestemme mottakerinformasjon, meldings-ID, emne og tidsstempel (eller senderinformasjon når du skanner den sendte mappen):

 offentlig funksjon parseHeader ($ header) // parser header objekt returnert fra imap_fetch_overview hvis (! isset ($ header-> fra)) return false;  ellers $ from_arr = imap_rfc822_parse_adrlist ($ header-> from, 'gmail.com'); $ fi = $ fra_arr [0]; $ msg = array ("uid" => (isset ($ header-> uid)) $ header-> uid: 0, "personal" => (isset ($ fi-> personlig))? @ imap_utf8 -> personlig): "", "email" => (isset ($ fi-> postkasse) && isset ($ fi-> verten))? $ fi-> postkasse. "@". $ fi-> vert: " "," postkasse "=> (isset ($ fi-> postkasse)) $ fi-> postkasse:" "," vert "=> (isset ($ fi-> verten))? $ fi-> vert:" "," subject "=> (isset ($ header-> subject))? @ imap_utf8 ($ header-> emne):" "," message_id "=> (isset ($ header-> message_id) > message_id: "", "in_reply_to" => (isset ($ header-> in_reply_to)) $ header-> in_reply_to: "", "utate" => (isset ($ header-> utate) > utate: 0, "date_str" => (isset ($ header-> date))? $ header-> date: ""); // håndterer henting med uid og rfc header parsing hvis ($ msg ['udate'] == 0 && isset ($ header-> date)) $ msg ['udate'] = strtotime ($ header-> date);  $ msg ['rx_email'] = "; $ msg ['rx_personal'] ="; $ msg ['rx_mailbox'] = "; $ msg ['rx_host'] ="; hvis (isset ($ header-> til)) $ to_arr = imap_rfc822_parse_adrlist ($ header-> til, 'gmail.com'); $ to_info = $ to_arr [0]; hvis (isset ($ to_info-> postkasse) && isset ($ to_info-> vert)) $ msg ['rx_email'] = $ to_info-> postkasse. '@'. $ to_info-> vert;  hvis (isset ($ to_info-> personal)) msg ​​['rx_personal'] = $ to_info-> personlig; hvis (isset ($ til_info-> postkasse)) msg ​​['rx_mailbox'] = $ til_info-> postkasse; hvis (isset ($ to_info-> host)) $ msg ['rx_host'] = $ til_info-> vert;  returner $ msg; 

Vi lager poster for avsenderen og meldingen konvolutten i vår database:

 // hopp over eventuelle systemmeldinger hvis ($ msg ['email'] == $ system_email) fortsette; // hvis utate er for gammel, hopp over msg if (time () - $ msg ['udate']> $ this-> scan_seconds) fortsett; // hoppe msg // standard handling $ action = selv :: ACTION_MOVE_FILTERED; $ isNew = $ s-> erNew ($ account_id, $ msg ["email"]); // se opp sender, hvis ny, opprett dem $ sender_id = $ s-> legg til ($ user_id, $ account_id, $ msg ["personal"], $ msg ["postkasse"], $ msg ["host"], 0); $ sender = Avsender :: modell () -> findByPk ($ sender_id); // opprett en melding i db om nødvendig $ message_id = $ m-> add ($ user_id, $ account_id, 0, $ sender_id, $ msg ['message_id'], $ msg ['subject'], $ msg ['utate '], $ msg [' in_reply_to ']); $ message = Melding :: modell () -> findByPk ($ message_id); 

Hvis avsenderen er ny for oss, ukjent, sender vi en hvitlisteutfordrings-e-post (vi snakker mer om hvitelistenes utfordringer i neste avsnitt nedenfor):

hvis ($ erNew) $ this-> challengeSender ($ user_id, $ account_id, $ sender, $ melding); 

Deretter avgjøre vi om brukeren kan ha trukket en melding fra en annen mappe tilbake til innboksen, og har tenkt å trene den via dra og slipp. Hvis ja, setter vi opplæringen til denne avsenderen til innboksen. Med andre ord, neste gang, vil vi bare sende meldinger fra denne avsenderen til innboksen:

 hvis ($ melding ['status'] == Melding :: STATUS_FILTERED || $ melding ['status'] == Melding :: STATUS_REVIEW || ($ melding ['status'] == Melding :: STATUS_TRAINED && $ message [ 'folder_id'] <> $ folder_id) || ($ melding ['status'] == Melding :: STATUS_ROUTED && $ message ['folder_id'] <> $ folder_id)) // da er det en trening $ action = selv :: ACTION_TRAIN_INBOX;  else if (($ message ['status'] == Melding :: STATUS_TRAINED || $ melding ['status'] == Melding :: STATUS_ROUTED) && $ melding ['folder_id'] == $ folder_id) // hvis trent allerede eller rutet til innboksen, hopper du over det $ action = selv :: ACTION_SKIP; ekko 'trent tidligere, hopp over'; lb (); Fortsette;  

Hvis ikke, forbereder vi oss på å flytte meldingen til Filtrering-mappen for videre behandling. Først kan vi sende varsler til brukerens telefon hvis det er en avsender-kamp eller søkeordkamp for varsler (og det er ikke stille timer):

 hvis ($ action == selv :: ACTION_MOVE_FILTERED) $ cnt + = 1; hvis $ sender-> exclude_quiet_hours == Sender :: EQH_YES eller! $ this-> isQuietHours ($ user_id)) // send smarttelefonvarsler basert på avsender hvis ($ sender-> varsel == Sender :: ALERT_YES) $ dette-> varsle ($ avsender, $ melding, Monitor :: NOTIFY_SENDER);  // sende varsler basert på søkeord hvis (AlertKeyword :: model () -> scan ($ msg)) $ this-> varsle ($ sender, $ melding, Monitor :: NOTIFY_KEYWORD);  // flytt imap msg til + Filtrering ekko 'Flytte til + Filtrering'; lb (); // $ result = @imap_mail_move ($ this-> stream, $ msg ['uid'], $ this-> path_filtering, CP_UID); $ result = $ this-> messageMoveHandler ($ msg ['uid'], $ this-> path_filtering, false); hvis ($ resultat) echo 'flyttet
'; $ M-> setStatus ($ message_id, Message :: STATUS_FILTERED);

Hvis meldingen ble trukket til innboksen, oppdaterer vi treningsinnstillingene våre:

ellers hvis ($ action == selv: ACTION_TRAIN_INBOX) // sett avsender folder_id til innboks ekko 'Train to Inbox'; lb (); $ M-> setStatus ($ message_id, Message :: STATUS_TRAINED); // bare togsender når meldingen er nyere enn siste innstilling hvis ($ msg ['utate']> = $ sender ['last_trained']) $ s-> setFolder ($ sender_id, $ folder_id); 

Prosessfiltreringsmetoden

Den sekundære prosesseringsmetoden kalles processFiltering, også i DaemonController.php. Det gjør de mer tidkrevende aspektene ved å flytte meldinger til de aktuelle mappene:

offentlig funksjon actionIndex () // behandler meldinger i @Filtering til aktuelle mapper $ r = ny Remote (); $ R-> processFiltering (); // Record timestamp av cronjob for overvåking $ file = file_put_contents ('./ protected / runtime / cronstamp.txt', tid (), FILE_USE_INCLUDE_PATH);  

Denne metoden åpner e-postkontoen din for å søke etter nylige meldinger og samle data om dem. Det bruker også imap_search, imap_fetch_overview og parseHeader:

$ tstamp = tid () - (7 * 24 * 60 * 60); // 7 dager siden $ recent_messages = @imap_search ($ this-> stream, 'SINCE' '.date ("j F Y", $ tstamp).' '', SE_UID); hvis ($ recent_messages === false) fortsett; // å gjøre - fortsett inn i neste konto $ result = imap_fetch_overview ($ this-> stream, implode (',', array_slice ($ recent_messages, 0, $ message_limit)), FT_UID); foreach ($ resultat som $ element) $ cnt + = 1; hvis (! $ this-> checkExecutionTime ($ time_start)) bryte; // få msg header og stream uid $ msg = $ this-> parseHeader ($ item); 

Den primære behandlingssløyfen for hver melding i filtreringsmappen er ganske detaljert. Først ser vi mottakeradressen, som SE tillater folk å trene mapper etter mottakeradresse, f.eks. meldinger til happyvegetarian.com-domenet går til veggie-mappen:

 // Angi standard handling for å flytte til gjennomgangmappen $ action = selv: ACTION_MOVE_REVIEW; $ destination_folder = 0; // se opp og opprett mottaker $ recipient_id = $ r-> legg til ($ user_id, $ account_id, $ msg ['rx_email'], 0); $ routeByRx = $ this-> routeByRecipient ($ recipient_id); hvis ($ routeByRx! == false) $ action = $ routeByRx-> handling; $ destination_folder = $ routeByRx-> destination_folder;  

Så ser vi senderen og lager en ny post i databasen (om nødvendig). Hvis opplæring eksisterer for avsenderen, kan vi angi målmappen:

 // se opp sender, hvis ny, opprett dem $ sender_id = $ s-> legg til ($ user_id, $ account_id, $ msg ["personal"], $ msg ["postkasse"], $ msg ["host"], 0); $ sender = Avsender :: modell () -> findByPk ($ sender_id); // hvis avsender destinasjon kjent, rute til mappe hvis ($ destination_folder == 0 && $ sender ['folder_id']> 0) $ action = self :: ACTION_ROUTE_FOLDER; $ destination_folder = $ avsender ['folder_id'];  

Hvis en uutdannet (ny) avsender har bekreftet seg via en Whitelist-utfordring (som vi skal diskutere i neste avsnitt nedenfor), vil vi sende denne meldingen til innboksen:

// whitelist verifiserte sendere går til innboksen hvis ($ sender-> is_verified == 1 && $ sender 'folder_id'] == 0 && UserSetting :: model () -> useWhitelisting ($ user_id)) // legg inn melding i innboks $ action = selv: ACTION_ROUTE_FOLDER; $ destination_folder = Mappe :: modell () -> oppslag ($ account_id, $ this-> path_inbox); 

Deretter oppretter vi en meldingsoppføring i databasen med konvoluttinformasjonen om denne meldingen:

 // opprett en melding i db $ message = Melding :: modell () -> findByAttributes (array ('message_id' => $ msg ['message_id']))); hvis (! tom ($ melding)) // meldingen eksisterer allerede, $ message_id = $ message-> id;  andre $ message_id = $ m-> legg til ($ user_id, $ account_id, 0, $ sender_id, $ msg ['message_id'], $ msg ['subject'], $ msg ['utate'], $ msg [ 'som svar på']);  

Hvis det er fra en ukjent, ubekreftet avsender, kan vi flytte meldingen til gjennomgangmappen. Gjennomgangsmappen inneholder alle meldingene fra sendere vi ikke gjenkjenner.

Hvis meldingen er fra en kjent sender og vi har en destinasjon i tankene, kan vi flytte den så lenge det ikke er stille timer (og ikke forstyrr, er av):

 hvis ($ recipient_id! = false) $ m-> setRecipient ($ message_id, $ recipient_id); hvis ($ action == selv :: ACTION_MOVE_REVIEW) echo 'Flytter til + filtrering / gjennomgang'; lb (); // $ result = @imap_mail_move ($ this-> stream, $ msg ['uid'], $ this-> path_review, CP_UID); $ result = $ this-> messageMoveHandler ($ msg ['uid'], $ this-> path_review, false); hvis ($ resultat) echo 'flyttet
'; $ M-> setStatus ($ message_id, Message :: STATUS_REVIEW); annet hvis ($ action == selv: ACTION_ROUTE_FOLDER || $ action == selv: ACTION_ROUTE_FOLDER_BY_RX) // oppslag mappenavn av folder_id $ folder = Mappe :: modell () -> findByPk ($ destination_folder); // hvis innboks og stille timer, ikke rute akkurat nå hvis (strtolower ($ mappe ['navn']) == 'innboks' og $ sender-> exclude_quiet_hours == Sender :: EQH_NO og $ this-> isQuietHours $ user_id)) fortsett; ekko 'Flytter til'. $ mappe ['navn']; lb (); $ mark_read = Mappe :: modell () -> isMarkRead ($ mappe ['mark_read']) || Sender :: modell () -> isMarkRead ($ avsender [ 'mark_read']); // $ result = @imap_mail_move ($ this-> stream, $ msg ['uid'], $ mappe ['navn'], CP_UID); $ result = $ this-> messageMoveHandler ($ msg ['uid'], $ mappe ['navn'], $ mark_read); hvis ($ resultat) echo 'flyttet
'; $ M-> setStatus ($ message_id, Message :: STATUS_ROUTED); $ M-> setFolder ($ message_id, $ destination_folder);

Under stille timer holdes meldingene primært i filtreringsmappen.

Hvert par timer vil en annen prosess bygge meldingen fordøyes ved hjelp av meldingstabelloppføringene for å avgjøre hvilke e-postmeldinger som nylig ble mottatt og filtrert og hvordan de ble rutet.

2. Implementere en Whitelist-utfordring til ukjente sendere

Målet med whitelistutfordringen er å holde enhver melding fra en ukjent avsender, f.eks. muligens en markedsføring bot eller spammer, ut av innboksen din. SE plasserer post fra ukjente sendere i oversiktsmappen. Men hvis du slår på whitelisting på, sender vi ut en utfordrings e-post som gir avsenderen en sjanse til å verifisere at de er menneskelige. Hvis de svarer, flytter vi meldingen til innboksen din. Hvis e-posten viser seg å være uønsket, kan du zap meldingen fra fordøyelsen eller dra den til en hvilken som helst mappe du ønsker å trene den til.

Brukeren kan slå hvitelisting på og av i innstillinger:

For å implementere whitelisting sender vi ut epostutfordringer når e-post kommer fra en ny avsender:

hvis ($ erNew) $ this-> challengeSender ($ user_id, $ account_id, $ sender, $ melding); 

ChallengeSender sender en kodet lenke til brukeren for at de skal klikke. Vi har også noen beskyttelser for å sikre at vi ikke fanger oss selv i en e-mail-sløyfe med en ut av kontormeddelelse:

 offentlig funksjon challengeSender ($ user_id, $ account_id, $ sender, $ melding) // whitelist email challenge $ yg = new Yiigun (); $ ac = Konto :: modell () -> findByPk ($ account_id); hvis (! tomt ($ ac ['challenge_name'])) $ fra = $ ac ['challenge_name']. ' mg_domain '>.'; ellers $ fra = 'Filter mg_domain '>.'; $ cred = Konto :: modell () -> getCredentials ($ ac-> cred); $ account_email = $ cred [0]; unset ($ cred); // sikkerhet: sjekker ingen nylig epost hvis ($ sender-> last_emailed> (tid () - (48 * 60 * 60))) returnerer false; hvis ($ sender-> isBot ($ sender ['email'])) // for å gjøre - kan også sette denne personen til masse som standard returnere false;  $ link = Yii :: app () -> getBaseUrl (true). "/ sender / verifiser / s /".$ sender-> id." / m /".$ melding-> id. '/ u /' . $ melding-> udate; $ subject = 'Vennligst bekreft meldingen du sendte til'. $ account_email; $ Body ="

Hei,

Jeg prøver å redusere uønsket e-post. Kan du bekrefte e-postadressen din ved å klikke på linken nedenfor:
'. $ Linken.

Ved å bekrefte e-postadressen din, vil du få raskere meldingen i innboksen. takk for din assistanse!

'; $ yg-> send_html_message ($ fra, $ avsender ['e-post'], $ emne, $ kropp); // oppdater last_emailed $ sender-> touchLastEmailed ($ sender-> ID);

Så, hvis mottakeren klikker på den kodede lenken, bekrefter vi dem i databasen. Senderkontrolløren behandler disse forespørslene og sjekker gyldigheten sin:

 offentlig funksjon actionVerify ($ s = 0, $ m = 0, $ u = 0) // bekreft at sikker msg url fra fordøyelsen er gyldig, logg inn bruker, vis msg $ sender_id = $ s; $ message_id = $ m; $ utate = $ u; $ msg = Melding :: modell () -> findByPk ($ message_id); hvis (! tom ($ msg) && $ msg-> sender_id == $ sender_id && $ msg-> utate == $ utate) $ result = 'Takk for din hjelp. Jeg svarer på e-posten din så snart som mulig. '; $ a = ny Avansert (); $ A-> verifySender ($ msg-> ACCOUNT_ID, $ SENDER_ID);  else $ result = 'Beklager, vi kunne ikke bekrefte e-postadressen din.';  $ this-> render ('verifiser', array ('result' => $ resultat,)); 

Dette forteller våre behandlingsløkker for å flytte denne og fremtidige meldinger fra denne avsenderen til innboksen.

3. Rapportering ubesvart e-post

Noen ganger hjelper det å se et sammendrag av meldinger du har sendt, men ikke mottatt svar. For å identifisere disse, forenkler e-postmeldinger som har blitt sendt, men ikke mottatt svar.

Hver melding vi mottar inneholder et unikt id, kalt message_id (del av IMAP-spesifikasjonen). Det ser ofte ut som dette:

Message-Id: 

Videre, når meldinger sendes som svar på andre meldinger, har de en som svar på felt som kobler tilbake til originalen message_id.

Så, vi bruker en SQL-spørring for å finne alle mottatte meldinger som ikke har en tilsvarende svarmelding som refererer til deres message_id. For dette bruker vi et LEFT OUTER JOIN der det er nei som svar på id:

offentlig funksjon getUnanswered ($ account_id, $ mode = 0, $ range_days = 7) hvis ($ modus == 0) $ subject_compare = 'ikke'; ellers $ subject_compare = "; $ query = Yii :: app () -> db-> createCommand (" SELECT fi_sent_message.id, fi_sent_message.recipient_id som sender_id, fi_sent_message.subject, fi_sent_message.udate, fi_message.in_reply_to, fi_sent_message.message_id FROM fi_sent_message VENSTRE YTRE JOIN FI_message ON FI_message.in_reply_to = fi_sent_message.message_id WHERE fi_sent_message.account_id = ". $ account_id." og fi_message.in_reply_to er null og fi_sent_message.udate> ". (tid () - (3600 * 24 * $ range_days) ). "og fi_sent_message.subject". $ subject_compare. "like" Re:% "BESTILL BY fi_sent_message.udate DESC") -> queryAll (); return $ query;

Vi bruker $ subject_compare modus for å skille mellom våre sendte meldinger som ikke er besvart og våre sendte svar på en tråd som ikke er besvart. Her er ubesvart meldingsrapporten i kontoen din:

SE tilbyr også denne informasjonen som en valgfri fordøyelse, kalt ubesvart e-postfordeling. Du kan motta det hver dag, hver dag eller hver uke.

Vi bruker også lignende SQL-tabeller med Google Charts for å gi rapporter om hvor ofte bestemte personer sender deg e-post:

 offentlig funksjon rapportInngang ($ account_id, $ range = 30, $ limit = 100) $ result = Yii :: app () -> db-> createCommand ('VELG FI_sender.personal, fi_sender.email, count (sender_id) som cnt Fra fi_message VENSTRE GÅ TIL FI_sender ON fi_sender.id = fi_message.sender_id HVOR fi_sender.account_id =: account_id og fi_message.created_at> DATE_SUB (NU (), INTERVAL: rekkevidde DAG) GRUPPE AV sender_id BESTILL BY cnt ned LIMIT: grense)) -> bindValue ( 'range', $ range) -> bindValue ( 'ACCOUNT_ID', $ ACCOUNT_ID) -> bindValue ( 'grense', $ grense) -> QueryAll (); returnere $ resultat;  

Jeg skal skrive mer om Google Charts for Tuts + snart. 

Neste skritt

Jeg håper du har funnet Forenkle Email spennende nok til å prøve deg på PHP IMAP programmering. Det er så mange kule funksjoner du kan bygge uten behov for de store e-postleverandørene til å gjøre noe nytt.

Hvis du har spørsmål eller rettelser, vennligst legg inn dem i kommentarene. Hvis du vil fortsette med mine fremtidige Tuts + opplæringsprogrammer og andre serier, vennligst følg @reifman eller besøk min forfatterside. Du kan også kontakte meg her.

Relaterte linker

Her er noen ekstra linker som du kan finne nyttige:

  • Forenkle e-post
  • Introduksjon til forenkle e-post (video)
  • Tolv Gmail-ideer for å revolusjonere e-post (igjen) 
  • Dekning av forenkle e-post i BoingBoing her og her
  • PHP IMAP-referanse
  • Introduksjon til Yii Framework (Tuts +)