'CRAM_MD5']; $imap=imap_open (IMAP_CONN,IMAP_USER,IMAP_PASS,NULL,1,$imap_options); if (!$imap){ echo 'IMAP errors:
'; foreach (imap_errors() as $err) echo $err.'
'; die(); } function verify_signature ($data,$sig) { $gnupg=gnupg_init(); $sig_details=gnupg_verify ($gnupg,$data,$sig); if (!$sig_details) throw new Exception ('signature verification failed'); $summary=$sig_details[0]['summary']; if ($summary & 0x0004) throw new Exception ('bad signature'); if ($summary & 0x0010) throw new Exception ('key has been revoked'); if ($summary & 0x0020) throw new Exception ('key has expired'); if ($summary & 0x0040) throw new Exception ('signature has expired'); if ($summary & 0x0080) throw new Exception ('can\'t verify: key missing'); if ($summary!=3) throw new Exception ('unknown signature verification problem ('.$summary.')'); return $sig_details[0]['fingerprint']; } function mail_fetch_message ($msg) { global $imap; $guessed_source=null; /* Fetch user */ $info=imap_headerinfo ($imap,$msg); $from=$info->from[0]->mailbox.'@'.$info->from[0]->host; $user=get_user_by_email ($from); /* Guess source */ if (strpos (imap_utf8 ($info->subject),'[agade]')!==false) $guessed_source='Agade'; /* Fetch the multipart tree */ $structure=imap_fetchstructure ($imap,$msg); if ($structure->type!=TYPEMULTIPART) throw new Exception ('not a multipart message'); if ($structure->subtype!='SIGNED') throw new Exception ('not a signed message'); /* Find the body and signature */ $body_id=null; $sig_id=null; foreach ($structure->parts as $id => $part){ if ($part->type==TYPEAPPLICATION && $part->subtype=='PGP-SIGNATURE') $sig_id=$id+1; else $body_id=$id+1; } if (is_null ($sig_id)) throw new Exception ('no signature attachment'); if (is_null ($body_id)) throw new Exception ('no message body'); /* Get contents */ $headers=imap_fetchmime ($imap,$msg,1,FT_INTERNAL | FT_PEEK); $body=imap_fetchbody ($imap,$msg,$body_id,FT_INTERNAL | FT_PEEK); $sig=imap_fetchbody ($imap,$msg,$sig_id,FT_PEEK); /* Verify signature */ $fpr=verify_signature ($headers.$body,$sig); if ($fpr!=$user['pgp_fingerprint']) throw new Exception ('illegal key used for signature'); /* Fetch plain-text body */ $body_part=$structure->parts[$body_id-1]; $plain_body=null; if ($body_part->type==TYPETEXT && $body_part->subtype=='PLAIN'){ $plain_body=$body; } else if ($body_part->type==TYPEMULTIPART){ foreach ($body_part->parts as $id => $part) if ($part->type==TYPETEXT && $part->subtype=='PLAIN') $plain_body=imap_fetchbody ($imap,$msg,$body_id.'.'.($id+1),FT_PEEK); } else { throw new Exception ('unknown body part type '.$body_part->type); } if (is_null ($plain_body)) throw new Exception ('no plain-text body'); $plain_body=imap_qprint ($plain_body); return [ 'user' => $user, 'body' => $plain_body, 'guessed_source' => $guessed_source ]; } function mail_get_unseen_messages () { global $imap; $unseen_msgs=imap_search ($imap,'UNSEEN'); if (!$unseen_msgs) $unseen_msgs=[]; return $unseen_msgs; } function mail_mark_seen ($msg) { global $imap; imap_setflag_full ($imap,$msg,'\Seen'); } function mail_finish () { global $imap; imap_close ($imap); } function mail_parse_message ($body,$prefill_info=[]) { $info=[ 'title' => null, 'location' => null, 'start_date' => null, 'end_date' => null, 'keywords' => [], 'source' => null, 'description' => null ]; $warnings=[]; foreach ($prefill_info as $key => $val) $info[$key]=$val; $lines=explode ("\n",$body); $headers=[]; $i=0; foreach ($lines as $line){ $i++; if (trim ($line)=='') break; $parts=explode (':',$line,2); if (count ($parts) > 1) $headers[]=['key' => trim ($parts[0]), 'val' => trim ($parts[1])]; else $headers[count ($headers)-1]['val'].=' '.trim ($line); } foreach ($headers as $header){ $key=$header['key']; $val=$header['val']; if (levenshtein ($key,'Title') < 2) $info['title']=$val; else if (levenshtein ($key,'Location') < 2) $info['location']=$val; else if (levenshtein ($key,'Source') < 2) $info['source']=$val; else if (levenshtein ($key,'Dates') < 2){ $parts=explode ('to',$val); if (count ($parts)==2){ $info['start_date']=trim ($parts[0]); $info['end_date']=trim ($parts[1]); } else { $info['start_date']=$info['end_date']=$val; } } else if (levenshtein ($key,'Keywords') < 2) $info['keywords']=array_map ('trim',explode (';',$val)); else $warnings[]='Unknown key '.$key; } $info['description']=trim (implode ("\n",array_slice ($lines,$i))); foreach (array_keys ($info) as $key) if (is_null ($info[$key])) $warnings[]='No '.$key.' found'; return [ 'info' => $info, 'warnings' => $warnings ]; }