2015-04-15 14:26:05 +02:00
< ? php
/**
* EGroupware - Mail - integration interface class
*
* @ link http :// www . egroupware . org
* @ package mail
* @ author Hadi Nategh [ hn @ stylite . de ]
* @ copyright ( c ) 2015 by Stylite AG < info - AT - stylite . de >
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
* @ version $Id : $
*/
2015-04-16 09:03:53 +02:00
2015-04-15 14:26:05 +02:00
/**
* Class cotains methods and functions
* to be used to integrate mail ' s message into other applications
*
2015-04-16 09:03:53 +02:00
*/
2015-04-15 14:26:05 +02:00
class mail_integration {
2015-04-16 09:03:53 +02:00
2015-04-15 14:26:05 +02:00
/**
* Public functions
* @ var type
*/
var $public_functions = array (
'integrate' => true
);
2015-04-16 09:03:53 +02:00
2015-04-15 17:55:18 +02:00
/**
* Maximum number of line characters ( - _ +=~ ) allowed in a mail , to not stall the layout .
* Longer lines / biger number of these chars are truncated to that max . number or chars .
*
* @ var int
*/
const MAX_LINE_CHARS = 40 ;
2015-04-16 09:03:53 +02:00
2015-04-15 14:26:05 +02:00
/**
* Gets requested mail information and sets them as data link
* - Execute registered hook method from the requested app for integration
* - with provided content from mail :
*
* - array ( 'addresses' => array (
* 'email' => stirng ,
* 'personel' => string ),
* 'attachments' => array (
* 'name' => string , // file name
* 'type' => string , // mime type
2015-04-17 11:39:22 +02:00
* 'egw_data' => string , // hash md5 id of an stored attachment in session (attachment which is in IMAP server)
* // NOTE: the attachmet either have egw_data OR tmp_name (e.g. raw mail eml file stores in tmp)
* 'tmp_name' => string ), // tmp dir path
* 'message' => string ,
* 'date' => string ,
* 'subject' => string ,
2015-04-20 16:31:21 +02:00
* ' entry_id => string // Id of the app entry which mail content will append to
2015-04-15 14:26:05 +02:00
* )
*
* @ param string $_to_emailAddress
* @ param string $_subject mail subject
* @ param string $_body mail message
* @ param array $_attachments attachments
* @ param string $_date
2015-04-16 09:03:53 +02:00
* @ param string $_rawMail path to file with raw mail
2015-04-17 11:39:22 +02:00
* @ param int $_icServerID mail profile id
2015-04-15 14:26:05 +02:00
* @ throws egw_exception_assertion_failed
*/
2015-04-16 09:03:53 +02:00
public static function integrate ( $_to_emailAddress = false , $_subject = false , $_body = false , $_attachments = false , $_date = false , $_rawMail = null , $_icServerID = null )
2015-04-15 14:26:05 +02:00
{
// App name which is called for integration
2015-04-16 09:03:53 +02:00
$app = isset ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ $_GET [ 'app' ]]) ? $_GET [ 'app' ] : null ;
2015-04-20 16:31:21 +02:00
// preset app entry id, selected by user from app_entry_dialog
$app_entry_id = $_GET [ 'entry_id' ];
2015-04-15 14:26:05 +02:00
// Set the date
2015-04-15 17:55:18 +02:00
if ( ! $_date )
{
$time = time ();
$_date = egw_time :: server2user ( $time -> now , 'ts' );
}
2015-10-27 11:29:57 +01:00
// For dealing with multiple files of the same name
$dupe_count = $file_list = array ();
2015-06-03 15:25:22 +02:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'currentapp' ] = $app ;
2015-09-11 16:00:33 +02:00
//error_log(__METHOD__.__LINE__.': RowID:'.$_GET['rowid'].': emailAddress:'. array2string($_to_emailAddress).' && '.$app);
2015-04-15 14:26:05 +02:00
// Integrate not yet saved mail
if ( empty ( $_GET [ 'rowid' ]) && $_to_emailAddress && $app )
{
$sessionLocation = 'mail' ;
$mailbox = base64_decode ( $_GET [ 'mailbox' ]);
2015-04-16 09:03:53 +02:00
2015-04-15 14:26:05 +02:00
if ( ! ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ $sessionLocation ][ 'saveAsOptions' ] === 'text_only' ) && is_array ( $_attachments ))
{
// initialize mail open connection requirements
if ( ! isset ( $_icServerID )) $_icServerID =& egw_cache :: getSession ( $sessionLocation , 'activeProfileID' );
$mo = mail_bo :: getInstance ( true , $_icServerID );
$mo -> openConnection ();
2015-09-11 16:00:33 +02:00
$messageUID = $messagePartId = $messageFolder = null ;
2015-04-15 14:26:05 +02:00
foreach ( $_attachments as $attachment )
{
2015-09-11 16:00:33 +02:00
//error_log(__METHOD__.__LINE__.array2string($attachment));
2015-04-15 14:26:05 +02:00
if ( trim ( strtoupper ( $attachment [ 'type' ])) == 'MESSAGE/RFC822' && ! empty ( $attachment [ 'uid' ]) && ! empty ( $attachment [ 'folder' ]))
{
$mo -> reopen (( $attachment [ 'folder' ] ? $attachment [ 'folder' ] : $mailbox ));
// get the message itself, and attach it, as we are able to display it in egw
// instead of fetching only the attachments attached files (as we did previously)
$message = $mo -> getMessageRawBody ( $attachment [ 'uid' ], $attachment [ 'partID' ],( $attachment [ 'folder' ] ? $attachment [ 'folder' ] : $mailbox ));
$headers = $mo -> getMessageHeader ( $attachment [ 'uid' ], $attachment [ 'partID' ], true , false ,( $attachment [ 'folder' ] ? $attachment [ 'folder' ] : $mailbox ));
$subject = mail_bo :: adaptSubjectForImport ( $headers [ 'SUBJECT' ]);
$attachment_file = tempnam ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'temp_dir' ], $GLOBALS [ 'egw_info' ][ 'flags' ][ 'currentapp' ] . " _ " );
$tmpfile = fopen ( $attachment_file , 'w' );
fwrite ( $tmpfile , $message );
fclose ( $tmpfile );
$size = filesize ( $attachment_file );
$attachments [] = array (
'name' => trim ( $subject ) . '.eml' ,
'mimeType' => 'message/rfc822' ,
'type' => 'message/rfc822' ,
'tmp_name' => $attachment_file ,
'size' => $size ,
);
}
else
{
if ( ! empty ( $attachment [ 'folder' ]))
{
$is_winmail = $_GET [ 'is_winmail' ] ? $_GET [ 'is_winmail' ] : 0 ;
2015-09-11 16:00:33 +02:00
$messageFolder = $attachment [ 'folder' ];
$messageUid = $attachment [ 'uid' ];
$messagePartId = $attachment [ 'partID' ];
2015-04-15 14:26:05 +02:00
$mo -> reopen ( $attachment [ 'folder' ]);
2015-09-11 16:00:33 +02:00
$attachmentData = $mo -> getAttachment ( $attachment [ 'uid' ], $attachment [ 'partID' ], $is_winmail , false , false , $attachment [ 'folder' ]);
2015-04-15 14:26:05 +02:00
$attachment [ 'file' ] = tempnam ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'temp_dir' ], $GLOBALS [ 'egw_info' ][ 'flags' ][ 'currentapp' ] . " _ " );
$tmpfile = fopen ( $attachment [ 'file' ], 'w' );
fwrite ( $tmpfile , $attachmentData [ 'attachment' ]);
fclose ( $tmpfile );
}
//make sure we search for our attached file in our configured temp_dir
if ( isset ( $attachment [ 'file' ]) && parse_url ( $attachment [ 'file' ], PHP_URL_SCHEME ) != 'vfs' &&
file_exists ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'temp_dir' ] . SEP . basename ( $attachment [ 'file' ])))
{
$attachment [ 'file' ] = $GLOBALS [ 'egw_info' ][ 'server' ][ 'temp_dir' ] . SEP . basename ( $attachment [ 'file' ]);
}
2015-10-27 11:29:57 +01:00
if ( in_array ( $attachment [ 'name' ], $file_list ))
{
$dupe_count [ $attachment [ 'name' ]] ++ ;
$attachment [ 'name' ] = pathinfo ( $attachment [ 'name' ], PATHINFO_FILENAME ) .
' (' . ( $dupe_count [ $attachment [ 'name' ]] + 1 ) . ')' . '.' .
pathinfo ( $attachment [ 'name' ], PATHINFO_EXTENSION );
}
2015-04-15 14:26:05 +02:00
$attachments [] = array (
'name' => $attachment [ 'name' ],
'mimeType' => $attachment [ 'type' ],
'type' => $attachment [ 'type' ],
'tmp_name' => $attachment [ 'file' ],
'size' => $attachment [ 'size' ],
);
2015-10-27 11:29:57 +01:00
$file_list [] = $attachment [ 'name' ];
2015-04-15 14:26:05 +02:00
}
}
2015-09-11 16:00:33 +02:00
if ( $messageFolder && $messageUid && $messagePartId && $mo -> isDraftFolder ( $messageFolder ) && ! $mo -> isTemplateFolder ( $messageFolder ))
{
//error_log(__METHOD__.__LINE__."#".$messageUid.'#'.$messageFolder);
try // message may be deleted already, as it maybe done by autosave
{
$mo -> deleteMessages ( array ( $messageUid ), $messageFolder );
}
catch ( egw_exception $e )
{
//error_log(__METHOD__.__LINE__." ". str_replace('"',"'",$e->getMessage()));
unset ( $e );
}
}
2015-04-15 14:26:05 +02:00
$mo -> closeConnection ();
}
// this one adds the mail itself (as message/rfc822 (.eml) file) to the app as additional attachment
// this is done to have a simple archive functionality (ToDo: opening .eml in email module)
2015-04-16 09:03:53 +02:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ $sessionLocation ][ 'saveAsOptions' ] === 'add_raw' &&
$_rawMail && file_exists ( $_rawMail ))
2015-04-15 14:26:05 +02:00
{
$subject = mail_bo :: adaptSubjectForImport ( $_subject );
$attachments [] = array (
'name' => trim ( $subject ) . '.eml' ,
'mimeType' => 'message/rfc822' ,
'type' => 'message/rfc822' ,
2015-04-16 09:03:53 +02:00
'tmp_name' => $_rawMail ,
'size' => filesize ( $_rawMail ),
2015-04-17 11:39:22 +02:00
'add_raw' => true
2015-04-15 14:26:05 +02:00
);
}
$toaddr = array ();
foreach ( array ( 'to' , 'cc' , 'bcc' ) as $x )
{
if ( is_array ( $_to_emailAddress [ $x ]) && ! empty ( $_to_emailAddress [ $x ]))
{
$toaddr = array_merge ( $toaddr , $_to_emailAddress [ $x ]);
}
}
$body_striped = strip_tags ( $_body ); //we need to fix broken tags (or just stuff like "<800 USD/p" )
$body_decoded = htmlspecialchars_decode ( $body_striped , ENT_QUOTES );
$body = mail_bo :: createHeaderInfoSection ( array ( 'FROM' => $_to_emailAddress [ 'from' ],
'TO' => ( ! empty ( $_to_emailAddress [ 'to' ]) ? implode ( ',' , $_to_emailAddress [ 'to' ]) : null ),
'CC' => ( ! empty ( $_to_emailAddress [ 'cc' ]) ? implode ( ',' , $_to_emailAddress [ 'cc' ]) : null ),
'BCC' => ( ! empty ( $_to_emailAddress [ 'bcc' ]) ? implode ( ',' , $_to_emailAddress [ 'bcc' ]) : null ),
'SUBJECT' => $_subject ,
'DATE' => mail_bo :: _strtotime ( $_date ))) . $body_decoded ;
2015-04-16 09:03:53 +02:00
2015-04-15 14:26:05 +02:00
$mailcontent = array (
'mailaddress' => implode ( ',' , $toaddr ),
'subject' => $_subject ,
'message' => $body ,
'attachments' => $attachments ,
'date' => $_date
);
}
// Integrate already saved mail with ID
2015-04-17 11:39:22 +02:00
else
2015-04-15 14:26:05 +02:00
{
// Initializing mail connection requirements
$hA = mail_ui :: splitRowID ( $_GET [ 'rowid' ]);
$sessionLocation = $hA [ 'app' ]; // THIS is part of the row ID, we may use this for validation
// Check the mail app
if ( $sessionLocation != 'mail' ) throw new egw_exception_assertion_failed ( lang ( 'Application mail expected but got: %1' , $sessionLocation ));
$uid = $hA [ 'msgUID' ];
$mailbox = $hA [ 'folder' ];
$icServerID = $hA [ 'profileID' ];
2015-04-16 09:03:53 +02:00
2015-04-15 14:26:05 +02:00
if ( $uid && $mailbox )
{
if ( ! isset ( $icServerID )) $icServerID =& egw_cache :: getSession ( $sessionLocation , 'activeProfileID' );
$mo = mail_bo :: getInstance ( true , $icServerID );
$mo -> openConnection ();
$mo -> reopen ( $mailbox );
2015-04-17 11:39:22 +02:00
$mailcontent = mail_bo :: get_mailcontent ( $mo , $uid , '' , $mailbox , false , true ,( ! ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ $sessionLocation ][ 'saveAsOptions' ] === 'text_only' )));
2015-04-15 14:26:05 +02:00
// this one adds the mail itself (as message/rfc822 (.eml) file) to the app as additional attachment
// this is done to have a simple archive functionality (ToDo: opening .eml in email module)
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ $sessionLocation ][ 'saveAsOptions' ] === 'add_raw' )
{
2015-04-17 11:39:22 +02:00
$message = $mo -> getMessageRawBody ( $uid , '' , $mailbox );
$headers = $mo -> getMessageHeader ( $uid , '' , true , false , $mailbox );
2015-04-15 14:26:05 +02:00
$subject = mail_bo :: adaptSubjectForImport ( $headers [ 'SUBJECT' ]);
2015-04-17 11:39:22 +02:00
$attachment_file = tempnam ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'temp_dir' ], $GLOBALS [ 'egw_info' ][ 'flags' ][ 'currentapp' ] . " mail_integrate " );
2015-04-15 14:26:05 +02:00
$tmpfile = fopen ( $attachment_file , 'w' );
fwrite ( $tmpfile , $message );
fclose ( $tmpfile );
$size = filesize ( $attachment_file );
$mailcontent [ 'attachments' ][] = array (
'name' => trim ( $subject ) . '.eml' ,
'mimeType' => 'message/rfc822' ,
'type' => 'message/rfc822' ,
'tmp_name' => $attachment_file ,
'size' => $size ,
2015-04-17 11:39:22 +02:00
'add_raw' => true
2015-04-15 14:26:05 +02:00
);
}
$mailcontent [ 'date' ] = strtotime ( $mailcontent [ 'headers' ][ 'DATE' ]);
}
}
2015-04-17 11:39:22 +02:00
2015-04-15 14:26:05 +02:00
// Convert addresses to email and personal
$addresses = imap_rfc822_parse_adrlist ( $mailcontent [ 'mailaddress' ], '' );
foreach ( $addresses as $address )
{
$email = sprintf ( '%s@%s' , trim ( $address -> mailbox ), trim ( $address -> host ));
$data_addresses [] = array (
'email' => $email ,
'name' => ! empty ( $address -> personal ) ? $address -> personal : $email
);
}
2015-04-16 09:03:53 +02:00
2015-04-15 17:55:18 +02:00
// shorten long (> self::max_line_chars) lines of "line" chars (-_+=~) in mails
2015-04-15 14:26:05 +02:00
$data_message = preg_replace_callback (
2015-04-15 17:55:18 +02:00
'/[-_+=~\.]{' . self :: MAX_LINE_CHARS . ',}/m' ,
2015-04-15 14:26:05 +02:00
function ( $matches ) {
2015-06-03 13:57:51 +02:00
return substr ( $matches [ 0 ], 0 , mail_integration :: MAX_LINE_CHARS );
2015-04-15 14:26:05 +02:00
},
$mailcontent [ 'message' ]
);
2015-04-16 09:03:53 +02:00
2015-04-15 14:26:05 +02:00
// Get attachments ready for integration as link
if ( is_array ( $mailcontent [ 'attachments' ]))
{
foreach ( $mailcontent [ 'attachments' ] as $key => $attachment )
{
$data_attachments [ $key ] = array (
2015-04-17 11:39:22 +02:00
'name' => $mailcontent [ 'attachments' ][ $key ][ 'name' ],
2015-04-15 14:26:05 +02:00
'type' => $mailcontent [ 'attachments' ][ $key ][ 'type' ],
2015-04-17 11:39:22 +02:00
'size' => $mailcontent [ 'attachments' ][ $key ][ 'size' ],
'tmp_name' => $mailcontent [ 'attachments' ][ $key ][ 'tmp_name' ]
2015-04-15 14:26:05 +02:00
);
2015-04-17 11:39:22 +02:00
if ( $uid && ! $mailcontent [ 'attachments' ][ $key ][ 'add_raw' ])
{
$data_attachments [ $key ][ 'egw_data' ] = egw_link :: set_data ( $mailcontent [ 'attachments' ][ $key ][ 'mimeType' ],
'emailadmin_imapbase::getAttachmentAccount' , array ( $icServerID , $mailbox , $uid , $attachment [ 'partID' ], $is_winmail , true ), true );
}
unset ( $mailcontent [ 'attachments' ][ $key ][ 'add_raw' ]);
2015-04-15 14:26:05 +02:00
}
}
2015-05-08 16:37:24 +02:00
// Check if the hook is registered
if ( $GLOBALS [ 'egw' ] -> hooks -> hook_exists ( 'mail_import' , $app ) == 0 )
{
// Try to register hook
if ( ! $GLOBALS [ 'egw' ] -> hooks -> register_single_app_hook ( $app , 'mail_import' ))
{
throw new egw_exception_assertion_failed ( 'Hook import_mail registration faild for ' . $app . ' app! Please, contact your system admin in order to clear cache and register hooks.' );
}
}
2015-04-15 14:26:05 +02:00
// Get the registered hook method of requested app for integration
2015-04-15 17:55:18 +02:00
$hook = $GLOBALS [ 'egw' ] -> hooks -> single ( array ( 'location' => 'mail_import' ), $app );
2015-06-03 15:25:22 +02:00
// Load translation for the app since the original URL
// is from mail integration and only loads mail translation
translation :: add_app ( $app );
2015-04-15 14:26:05 +02:00
// Execute import mail with provided content
2015-04-15 17:55:18 +02:00
ExecMethod ( $hook [ 'menuaction' ], array (
2015-04-15 14:26:05 +02:00
'addresses' => $data_addresses ,
'attachments' => $data_attachments ,
'message' => $data_message ,
'date' => $mailcontent [ 'date' ],
2015-04-20 16:31:21 +02:00
'subject' => $mailcontent [ 'subject' ],
'entry_id' => $app_entry_id
2015-04-15 14:26:05 +02:00
));
}
}