'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
];
}