📜 ⬆️ ⬇️

Upload photos to the site using email

This is my first post on Habré, so do not judge strictly.

Task.


Implement the ability to upload photos to a profile or photo event tape via e-mail, place them in the specified folder and make a corresponding entry in the database.

Algorithm


The user sends an email with photos to the userXXX_eventYYY@mysite.com type address , where eventYYY is the event ID; userXXX - user ID. This e-mail address DOES NOT EXIST. Therefore, all letters sent to non-existent addresses are redirected to image_upload@mysite.com. Then, when reading mail from this address, parse the headers and find out to which address the letter was originally sent. Parse the received address, find out where to put the files and who flooded them.

Using PEAR


To work with the POP3 server, the PEAR library was used, in particular the class Net_POP3 , which is located in the file path / to / pear / Net / POP3.php . For its successful work, the class Net_Socket ( path / to / pear / Net / Socket.php ) and, in fact, PEAR.php are required. All these files are located at http://pear.php.net and are available for download.
If you do not have PEAR installed - just copy POP3.php and Socket.php to your folder with libraries and overwrite the paths in them. The PEAR.php file is in the path / to / pear / folder.
')

Additional functions


For processing attached files I needed some more functions. I will not ascribe to themselves their authorship. They are taken from the site http://webi.ru/webi_articles/6_12_f.html and slightly altered (quite a bit).
In my code, they look like this:
/* START FUNCTIONS BLOCK */
// boundary Content-Type
function get_boundary($ctype){
if (preg_match( '/boundary[ ]?=[ ]?(["]?.*)/i' ,$ctype,$regs)) {
$boundary = preg_replace( '/^\"(.*)\"$/' , "\\1" , $regs[1]);
return trim( "--$boundary" );
}
}

// (, ..)
// ( ), boundary
function split_parts($boundary,$body) {
$startpos = strpos($body,$boundary)+strlen($boundary)+2;
$lenbody = strpos($body, "\r\n$boundary--" ) - $startpos;
$body = substr($body,$startpos,$lenbody);
return explode($boundary. "\r\n" ,$body);
}

//
function fetch_structure($email) {
$ARemail = Array();
$separador = "\r\n\r\n" ;
$header = trim(substr($email,0,strpos($email,$separador)));
$bodypos = strlen($header)+strlen($separador);
$body = substr($email,$bodypos,strlen($email)-$bodypos);
$ARemail[ "header" ] = $header;
$ARemail[ "body" ] = $body;
return $ARemail;
}

// ,
function decode_header($header) {
$headers = explode( "\r\n" ,$header);
$decodedheaders = Array();
foreach ($headers as $header_item){
$thisheader = trim($header_item);
if (!empty($thisheader))
{
if (!ereg( "^[A-Z0-9a-z_-]+:" ,$thisheader))
$decodedheaders[$lasthead] .= " $thisheader" ;
else {
$dbpoint = strpos($thisheader, ":" );
$headname = strtolower(substr($thisheader,0,$dbpoint));
$headvalue = trim(substr($thisheader,$dbpoint+1));
if ($decodedheaders[$headname] != "" )
$decodedheaders[$headname] .= "; $headvalue" ;
else
$decodedheaders[$headname] = $headvalue;
$lasthead = $headname;
}
}
}
return $decodedheaders;
}

// .
// .
// .
function compile_body($body,$enctype,$ctype) {
$enctype = explode( " " ,$enctype); $enctype = $enctype[0];
if (strtolower($enctype) == "base64" )
$body = base64_decode($body);
elseif(strtolower($enctype) == "quoted-printable" )
$body = quoted_printable_decode($body);
if (ereg( "koi8" , $ctype)) $body = convert_cyr_string($body, "k" , "w" );
return $body;
}
/* END FUNCTIONS BLOCK */


* This source code was highlighted with Source Code Highlighter .


Main code (email_upload.php)


Now that everything is ready, it's time to write a script for receiving letters and processing them.
First, create an object $ pop3 and connect to the server.

$user= 'username' ;
$pass= 'secure' ;
$host= 'mysite.com' ;
$port= "110" ;

//
$pop3 =& new Net_POP3();

//
if (PEAR::isError( $ret= $pop3->connect($host , $port ) )){
echo "ERROR: " . $ret->getMessage() . "\n" ;
exit();
}

//
if (PEAR::isError( $ret= $pop3->login($user , $pass, 'USER' ) )){
echo "ERROR: " . $ret->getMessage() . "\n" ;
exit();
}


* This source code was highlighted with Source Code Highlighter .


Now everything is ready to receive the list of letters and their processing. This and do

$message_list=$pop3->getListing(); // .

* This source code was highlighted with Source Code Highlighter .


Go through all the letters in the cycle:

foreach ($message_list as $message){
$filenames[] = array();
/* START GET PARSED HEADERS */
//
$message_id = $message[ 'msg_id' ];
//
$headers = $pop3->getParsedHeaders($message_id);

$type = $ctype = $headers[ 'Content-Type' ];
$ctype = split( ";" ,$ctype);
$types = split( "/" ,$ctype[0]);
$maintype = trim(strtolower($types[0]));
$subtype = trim(strtolower($types[1]));

/* END GET PARSED HEADERS */
/* START CREATE FILE LOCATION AND SQL DATA*/

//
$from_user_info = $headers[ 'Delivered-To' ];

//
preg_match( '/(user[0-9]+)_(event[0-9]+)@mysite.com/' , $from_user_info, $matches);
$user_id = str_replace( "user" , "" , $matches[1]);
$event_id = str_replace( "event" , "" , $matches[2]);

//
$file_location = "/path/to/upload" ;

// SQL
$table_data = array(
'user_id' => $user_id,
'event_id' => $event_id
);

/* END CREATE FILE LOCATION AND SQL DATA*/

/* START GET BODY */
//
$message_text = htmlspecialchars($pop3->getBody($message_id));

// ( )
if ($maintype== "multipart" && ereg($subtype, "signed,mixed,related" )) //
{
// -
$boundary=get_boundary($headers[ 'Content-Type' ]);

//
$part = split_parts($boundary,$message_text);

//
foreach ($part as $part_item){
//
$email = fetch_structure($part_item);
$header = $email[ "header" ];
$body = $email[ "body" ];

//
$headers = decode_header($header);
$ctype = $headers[ "Content-Type" ];
$cid = $headers[ "content-id" ];
$Actype = split( ";" ,$ctype);
$types = split( "/" ,$Actype[0]);
$rctype = strtolower($Actype[0]);

// ,
$is_download = (ereg( "name=" ,$headers[ "content-disposition" ].$headers[ "content-type" ]) || $headers[ "X-Attachment-Id" ] != "" || $rctype == "message/rfc822" );

if ($is_download) {
// Content-Type Content-Disposition
$cdisp = $headers[ "content-disposition" ];
$ctype = $headers[ "content-type" ];
$ctype2 = explode( ";" ,$ctype);
$ctype2 = $ctype2[0];
$Atype = split( "/" ,$ctype);
$Acdisp = split( ";" ,$cdisp);
$fname = $Acdisp[1];
if (ereg( "filename=\"(.*)\"" ,$fname,$regs))
$filename = $regs[1];
if ($filename == "" && ereg( "name=(.*)" ,$ctype,$regs))
$filename = $regs[1];
$filename = ereg_replace( "\"(.*)\"" , "\\1" ,$filename);
$filename = ereg_replace( ""(.*)"" , "\\1" ,$filename);

// .
$body = compile_body($body,$headers[ "content-transfer-encoding" ],$ctype);

//
$filename = $file_location.trim($filename);

//
$filenames[] = $filename;
//
$ft=fopen($filename, "wb" );
fwrite($ft,$body);
fclose($ft);
}
}
}

// $filenames[] $table_data .
$query = "INSERT INTO event_foto(event_id, user_id, image_name) VALUES " ;
$total_fotos = count($filenames);
$current = 1;
foreach ($filenames as $file){
$query .= "('$event_id','$user_id','$file')" ;
if ($total_fotos>$current)
$query .= ", " ;
$current++;
}
mysql_query($query);
//
$pop3->deleteMsg($message_id);
}


* This source code was highlighted with Source Code Highlighter .


the end


Actually everything. The module is working. It remains only to hang this file on the CRON (for example, every hour).
Thanks for attention. Good luck!

Source: https://habr.com/ru/post/77304/


All Articles