Etikettarkiv: mail

Så tar du emot och hanterar E-post i PHP

Bild CC flickr.com/photos/9009139@N08/2959912279När jag byggde Bloggy för några år sedan så byggde jag även in en funktion för att ta emot bilder och text från E-post samt MMS-meddelanden till PHP.

Det som sedan händer är att PHP-koden parsar meddelandet och hämtar ut olika delar såsom rubrik (subject), meddelande och eventuella bilder som är bifogade.

Men först lite beroenden, denna guide fungerar enbart om du har en VPS eller egen server med Sendmail, PHP och pear-paketet Mail_mimeDecode. Pear-paketet kan installeras på följande sätt:

# pear install Mail_mimeDecode

Först måste vi konfigurera Sendmail att ta emot brev för vissa adresser. Detta förfarande har jag automatiserat genom att generera en virtusertable-fil i /etc/mail-katalogen. Du kan behöva uppdatera din sendmail.mc med nedan och generera en ny sendmail.cf:

FEATURE(`virtusertable’,`hash -o /etc/mail/virtusertable’)dnl

Alternativt så kan du direkt via /etc/aliases sätta upp följande snutt som gör så att inkommande E-post hamnar hos PHP:

mms:  ”| /usr/bin/php /var/www/bloggy.se/docs/newmail.php”

Det som händer då är att allt som går till [email protected] alternativt det som routas via virtusertable till [email protected] på följande sätt:

[email protected] [email protected]

Hamnar i PHP hos newmail.php och kommer in som stdin. Obs, om du ändrar i aliases, virtusertable eller .mc-filen så måste du generera nya filer (med kommandot newaliases eller makemap hash exempelvis). Följande kod använder jag sedan för att parsa mailet:

  define("DOMAIN", "bloggy.se");

  include_once('Mail/mimeDecode.php');

  $input = file_get_contents("php://stdin");
  $from = "unknown";

  @file_put_contents("/tmp/maillog.txt", $input."\n--- new mail --\n", FILE_APPEND);

  $params['include_bodies'] = true;
  $params['decode_bodies'] = true;
  $params['decode_headers'] = true;
  $params['input'] = $input;

  $structure = Mail_mimeDecode::decode($params);

  $to = $structure->headers['to'];
  $from = $structure->headers['from'];

  #mailme('<pre>'.print_r($header, true).'</pre>'); // For debugging
  $header = imap_rfc822_parse_headers($input);

  foreach($header as $foo => $bar) {
    if($foo == 'to' || $foo == 'cc') {
        foreach($bar as $k) {
            if($k->host == DOMAIN) {
                $dste = $k->mailbox;
            }
        }
    }
  }

  foreach ($structure->parts as $part) {
    // Save text
    if (isset($part->ctype_primary) && $part->ctype_primary == "text") {
        if(strlen($part->body) > 2 && !preg_match("/iPhone$/", $part->body))
            $text = $part->body;
    }
  }
  if(!$text)
    $text = $header->headers['subject'];

  if(!$text)
    $text = $structure->headers['subject'];

Och slutligen så hamnar antingen innehållet i mailet eller rubriken i $text om vi har tur.

Strul med den elektroniska posten

Jag har pysslat rätt länge med E-post, för över 10 år sedan så byggde jag system som slussade E-post över UUCP men sedan dess så har jag inte lagt så mycket krut eftersom mail (SMTP) oftast är ett såntdär protokoll som bara fungerar så länge man inte rör något. Oja, jag har nog lyckats att göra alla fel man kan göra och hamnat i alla möjliga RBL-listor (förr i tiden då standard var att släppa igenom allt).

Men idag då jag kollade igenom diverse konton som hade fått studsmail som låg och skräpade så fann jag att några E-brev från tjänsterna blogbackupr, bloggbackup samt från denna bloggs WordPress inte hade kommit fram som de skulle så jag hittade två faktorer:

1. CPU-belastningen på den VPS som jag hyr är på tok för hög vilket resulterar i att sendmail slutar ta emot mail:

Processen säger ”sendmail: MTA: rejecting connections on daemon MSP-v4: load average: 35”

och lasten är enligt följande: load average: 34.92, 35.41, 35.42

Om du ändå vill ta emot E-post så konfigureras detta sendmail.cf med följande parametrar:

# load average at which we just queue messages
O QueueLA=

# load average at which we refuse connections
O RefuseLA=

# load average at which we delay connections; 0 means no limit O
DelayLA=

2. Return-path är felaktig satt vilket gör att vissa mailservrar inte tar emot mail som skickas via PHP-funktionen mail()

Detta åtgärdas genom att sätta PHP.INI-konfigurationsvärdet ”sendmail_from”. Kan sättas i godtycklig php-kod på följande sätt innan mail() anropas:

ini_set(”sendmail_from”, ”[email protected]”);

Så får vi hoppas att detta löst mailproblemen för denhär gången.

Update: Det löste tyvärr inte problemet. Var även tvungen att lägga till ”-r [email protected]” som fjärde argument till PHP-funktionen mail() så löste det mitt problem.