I'm trying to create a piece of code that will go into the mailbox and take out the attachments of a specific file. So far I am only able to view if there is an attachment or if there is not an attachment on the e-mail.
But I want it to be able to take the attachments out of the e-mail and then save them to a specified directory. The type of attachment I'm trying to take out is a .jpg
I've tried a bunch of different pieces of code that I've found on google and I've been trying to tailor it to fit into my code, but so far I have been unsuccessful in finding anything that works correctly.
I was wondering if anyone would be able to help me create a piece of code that would be able to take the attachments out of the emails and store them in a directory.
Thanks.
<?php
/* connect to email */
$hostname = '{*****.com:110/pop3}INBOX';
$username = '*****';
$password = '*****';
// try to connect
$inbox = imap_open($hostname,$username,$password) or die('Cannot connect to server: ' . imap_last_error());
// grab emails
$emails = imap_search($inbox,'ALL');
// Search for the 39th email, which has an attachment
$count = 39;
// Fetch all the information about an email
$attachment = imap_fetchstructure($inbox, $count);
// find out how may parts the object has
$numparts = count($attachment->parts);
// find if if multipart message
if ($numparts >= 2) {
foreach ($attachment->parts as $part) {
if ($part->disposition == "INLINE") {
// inline message. Show number of lines
printf("Inline message has %s lines<BR>", $part->lines);
} elseif ($part->disposition == "ATTACHMENT") {
// an attachment
echo "Attachment found!";
// print out the file name
echo "Filename: ", $part->dparameters[0]->value;
}
}
}
//}
else {
// only one part so get some useful info
echo "No attachment";
}
imap_close($imap);
?>
Instead of imap_search I used imap_check to retrieve messages overview, and the following worked.
Go over messages found with imap_check, and this is how you extract the binary data of attachment:
$mbox = imap_open( . . . . );
$IMAPobj = imap_check($inbox);
$start = $IMAPobj->Nmsgs-30;
$end = $IMAPobj->Nmsgs;
$result = imap_fetch_overview($inbox,"$start:$end",0);
$count = $end;
foreach ($result as $overview) {
$parts = mail_mime_to_array($inbox, $count);
foreach($parts as $part) {
if(#$part['filename'] || #$part['name'] ) {
$partName = $part['filename'] ? $part['filename'] : $part['name'];
echo "Attachment name is " . basename($partName);
echo "\n";
if(preg_match( . . . write here a regex to detect ".jpg" in $partName . . .)) {
echo "Found file! Extracting binary data...";
$fileContents = $part['data'];
file_put_contents("attachment.jpg", $fileContents);
}
}
}
}
Related
Connect to my e-mail account to read the messages and download the attachments to the server by PHP code
I have used so far with the third code that appears here
Indeed [from GuRu]
Here is a copy of the code if it can make it easier for members.
<?php
set_time_limit(3000);
/* connect to gmail with your credentials */
$hostname = '{imap.gmail.com:993/imap/ssl}INBOX';
$username = 'YOUR_USERNAME';
$password = 'YOUR_PASSWORD';
/* try to connect */
$inbox = imap_open($hostname,$username,$password) or die('Cannot connect
to Gmail: ' . imap_last_error());
$emails = imap_search($inbox, 'FROM "abc#gmail.com"');
/* if any emails found, iterate through each email */
if($emails) {
$count = 1;
/* put the newest emails on top */
rsort($emails);
/* for every email... */
foreach($emails as $email_number)
{
/* get information specific to this email */
$overview = imap_fetch_overview($inbox,$email_number,0);
$message = imap_fetchbody($inbox,$email_number,2);
/* get mail structure */
$structure = imap_fetchstructure($inbox, $email_number);
$attachments = array();
/* if any attachments found... */
if(isset($structure->parts) && count($structure->parts))
{
for($i = 0; $i < count($structure->parts); $i++)
{
$attachments[$i] = array(
'is_attachment' => false,
'filename' => '',
'name' => '',
'attachment' => ''
);
if($structure->parts[$i]->ifdparameters)
{
foreach($structure->parts[$i]->dparameters as $object)
{
if(strtolower($object->attribute) == 'filename')
{
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['filename'] = $object->value;
}
}
}
if($structure->parts[$i]->ifparameters)
{
foreach($structure->parts[$i]->parameters as $object)
{
if(strtolower($object->attribute) == 'name')
{
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['name'] = $object->value;
}
}
}
if($attachments[$i]['is_attachment'])
{
$attachments[$i]['attachment'] = imap_fetchbody($inbox,
$email_number, $i+1);
/* 3 = BASE64 encoding */
if($structure->parts[$i]->encoding == 3)
{
$attachments[$i]['attachment'] =
base64_decode($attachments[$i]['attachment']);
}
/* 4 = QUOTED-PRINTABLE encoding */
elseif($structure->parts[$i]->encoding == 4)
{
$attachments[$i]['attachment'] =
quoted_printable_decode($attachments[$i]['attachment']);
}
}
}
}
/* iterate through each attachment and save it */
foreach($attachments as $attachment)
{
if($attachment['is_attachment'] == 1)
{
$filename = $attachment['name'];
if(empty($filename)) $filename = $attachment['filename'];
if(empty($filename)) $filename = time() . ".dat";
$folder = "attachment";
if(!is_dir($folder))
{
mkdir($folder);
}
$fp = fopen("./". $folder ."/". $email_number . "-" .
$filename, "w+");
fwrite($fp, $attachment['attachment']);
fclose($fp);
}
}
}
}
/* close the connection */
imap_close($inbox);
echo "all attachment Downloaded";
?>
Attachment whose name in English or in numbers comes in wonderful!
But if the name is in Hebrew, the file name comes encoded like this:
1424 - =? UTF-8? B? 15TXntec16bXlCDXoteR15XXqCDXkNek15zXkdeQ15XXnSDXkg ==? = =? UTF-8? B? 150g16jXkSDXkteV15DXnNee158yICgxKS5qcGc =? =
I've been searching for a few days at any time of the day, I've tried lots of codes. In the meantime,
I don't know what to do!
(Maybe I'm just not putting the fixes in the right place? Anyway at the moment I'm really desperate and would be very happy for any practical solution if someone could help please.)
Here are some attempts:
Sending an email with attachment displays in encoded format PHP
I think this is exactly the title of my problem. But I couldn't figure out the answers in a way that I could incorporate in my code or the code offered here
setting encoding for attachment in phpmailer
While it's not exactly related, it might help. Anyway, I couldn't make it
Reload this Page PHP: Send email with attachment and UTF8 in filenames
Base 64 Attachment in PHP Mail() not working
While it does offer a code, it is a code for sending and receiving emails. How can this help me?
Sending MIME-encoded email attachments with utf-8 filenames
Same question
PHP - Convert string to unicode
I couldn't integrate that into the code
How to read the Content Type header and convert into utf-8 while Gmail IMAP has utf8 and Outlook has ISO-8859-7?
Didn't help me
And that's just part ...
I would be very grateful for any idea
Thank you!!
After a lot of searches and attempts, this line saved the situation: It is brought by Mister jlh on this page:
iconv_mime_decode($str, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8')
I put it here:
$filename = $attachment['name'];
$filename = iconv_mime_decode($filename, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8');
if(empty($filename)) $filename = $attachment['filename'];
I hope it helps to do more good things
first sorry for my english
I have array will used by function
Upload text file and every line will be element in array
$fh = fopen("upload/".'1.txt','r');
$conn = array();
while ($line = fgets($fh)) {
$conn[] = $line;
}
fclose($fh);
$wbs->SendBulk($conn, "hello world");
Go To Function
public function SendBulk($targets, $message)
{
echo "Sending " . count($targets) . " bulk messages...<br />";
foreach($targets as $target)
{
$this->wa->sendPresenceSubscription($target);
$this->wa->pollMessages();
$this->wa->sendMessageComposing($target);
sleep(55);
$this->wa->pollMessages();
$this->wa->sendMessagePaused($target);
static::$sendLock = true;
echo "Sending message from " . $this->username . " to $target... ";
$this->wa->sendMessage($target, $message); // Orginal
while(static::$sendLock)
{
//wait for server receipt
sleep(55);
}
}
My Problem If I have in text file 2 or more element in array
will send for the last element a message
but If i make array like this
$conn= array("565684898", "484849815", "484897987", "515498798");
It work for all elements
Please Help
The string returned by fgets() includes the newline that ends each line. Use rtrim() to remove it:
$conn[] = rtrim($line);
You can also replace your entire code that reads the file with:
$conn = file('upload/1.txt', FILE_IGNORE_NEW_LINES)
I've got a script running when a certain email address receives an email, procmail pipes to a PHP script, which is then parsed by Plancake, not many problems there. I've got an if statement on strpos, depending on if the body contains a certain text. For some reason, when I add the MySQL code, the entire thing stops working. Unfortunately the way it's setup I'm not quite sure how to add error checking. Here's the code:
<?php
require_once("PlancakeEmailParser.php");
$rawEmail = '';
if (($fp = fopen('php://stdin', 'r')) !== false) {
while (!feof($fp)) {
$rawEmail .= fread($fp, 1024);
}
fclose($fp);
}
$emailParser = new PlancakeEmailParser($rawEmail);
$emailSubject = $emailParser->getSubject();
$emailBody = $emailParser->getPlainBody();
$emailHeader = $emailParser->getHeader('From');
$message = "FROM: ".$emailHeader."\n\nSubject: ".$emailSubject."\n\nBody: ".$emailBody;
$status = 4;
preg_match("/\d+/", "$emailSubject", $matches);
$number = $matches[0];
$short = substr($message, 0, strpos( $message, 'Begin'));
if (stripos($short,'approve') !== false) {
echo 'true';
$msg = approve;
//file_put_contents('/home/symantec_mail/task' . $number . 'short.php',$msg);
file_put_contents('/home/symantec_mail/task' . $number . 'approve_short_reply.txt',$message);
file_put_contents('/home/symantec_mail/task' . $number . 'approve_reply.txt',$rawEmail);
}
if (stripos($short,'complete') !== false) {
echo 'true';
$msg = complete;
when I uncomment the following mysqli code, everything stops.
//$mysqli = new mysqli("localhost", "user", "pass", "db");
//$update = $mysqli->prepare("UPDATE task_overview SET status = ? WHERE task_id = ?");
//$update->bind_param('ii', $status, $number");
//$update->execute();
rest of the code.
//file_put_contents('/home/symantec_mail/task' . $number . 'short.php',$msg);
file_put_contents('/home/symantec_mail/' . $number . 'complete_short_reply.txt',$message);
file_put_contents('/home/symantec_mail/' . $number . 'complete_reply.txt',$rawEmail);
}
?>
Really not sure why I can't execute these commands. I will point out that it's on a different shell account than my normal web server, although the PHP is still executing, I'm really not sure if I'm communicating with the MySQL server. Please if you have any suggestions, even if it's for error checking I'll greatly appreciate it.
I'm trying to get 'email message' from any Email Service Provider, like: yahoo, Gmail, Hotmail. But I can't get it. It's show error message.
Following is my php script..
<?php
if( $mbox = imap_open("{yoursitename.com:110/pop3/notls}INBOX", "username of mailbox",
"password of mailbox")){
$path = "set path here for where the attachments are store";
$check = imap_mailboxmsginfo($mbox);
function getmsg($mbox,$mid) {
global $charset,$htmlmsg,$plainmsg,$attachments,$from,$to,$subj,$timages,$path;
$htmlmsg = $plainmsg = $charset = '';
$attachments = array();
// HEADER
$h = imap_headerinfo($mbox,$mid);
// add code here to get date, from, to, cc, subject...
$date = $h->date;
$from = $h->fromaddress;
$to = $h->toaddress;
$subj = htmlspecialchars($h->Subject);
// BODY
$s = imap_fetchstructure($mbox,$mid);
if (!$s->parts) // simple
getpart($mbox,$mid,$s,0); // pass 0 as part-number
else { // multipart: cycle through each part
foreach ($s->parts as $partno0=>$p)
getpart($mbox,$mid,$p,$partno0+1);
}
}
function getpart($mbox,$mid,$p,$partno) {
// $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple
global
$htmlmsg,$plainmsg,$charset,$attachments,$partid,$last_mail_id,$patterns,$pic,
$newstr,$c,$ok,$timages,$subj,$path;
$patterns = array();
$pic = array();
$image=array();
$data = ($partno) ? imap_fetchbody($mbox,$mid,$partno) : imap_body($mbox,$mid);
// simple
if ($p->encoding==4)
$data = quoted_printable_decode($data);
else if ($p->encoding==3)
$data = base64_decode($data);
// PARAMETERS // get all parameters, like charset, filenames of attachments,
etc.
$params = array();
if ($p->parameters)
foreach ($p->parameters as $x)
$params[strtolower($x->attribute)] = $x->value;
if ($p->dparameters)
foreach ($p->dparameters as $x)
$params[strtolower($x->attribute)] = $x->value;
// ATTACHMENT // Any part with a filename is an attachment,
// so an attached text file (type 0) is not mistaken as the message.
if ($params['filename'] || $params['name']) {
$partid = htmlentities($p->id,ENT_QUOTES);
// filename may be given as 'Filename' or 'Name' or both
$filename = ($params['filename'])? $params['filename'] : $params['name'];
// filename may be encoded, so see imap_mime_header_decode()
$attachments[$filename] = $data; // this is a problem if two files have same name
//store id and filename in array
$image[$key] = $filename;
}
//save the attachments in the directory
foreach( $attachments as $key => $val){
$fname = $key;
$fp = fopen("$path/$fname","w");
fwrite($fp, $val);
fclose($fp);
}
// TEXT
if ($p->type==0 && $data) {
// Messages may be split in different parts because of inline attachments,
// so append parts together with blank row.
if (strtolower($p->subtype)=='plain')
$plainmsg .= trim($data)."\n\n";
else
//preg_match_all('/<img[^>]+>/i',$data, $result);
$htmlmsg .= $data."<br><br>";
$charset = $params['charset']; // assume all parts are same charset
}
// There are no PHP functions to parse embedded messages, so this just appends the
raw source to the main message.
else if ($p->type==2 && $data) {
$plainmsg .= $data."\n\n";
}
// SUBPART RECURSION
if ($p->parts) {
foreach ($p->parts as $partno0=>$p2)
getpart($mbox,$mid,$p2,$partno.'.'.($partno0+1)); // 1.2, 1.2.1, etc.
}
}
$attachments = array();
$num_msg = imap_num_msg($mbox);
if($num_msg>0) {
getmsg($mbox,1);
}else {
echo "Sorry!...No Messages in MailBox...<br>";
}
//imap_delete and imap_expunge are used to delete the mail after fetching....Uncomment
it if you want to delete the mail from mailbox
//imap_delete($mbox,1);
//imap_expunge($mbox);
imap_close($mbox);
}else { exit ("Can't connect: " . imap_last_error() ."\n"); echo "FAIL!\n"; };
?>
error message:
Warning: imap_open() [function.imap-open]: Couldn't open stream {yahoo.com:110/pop3
/notls}INBOX in D:\xampp server\xampp\htdocs\practice\php\email.php on line 2
Fatal error: Maximum execution time of 30 seconds exceeded in D:\xampp server\xampp
\htdocs\practice\php\email.php on line 2
Notice: Unknown: Can't connect to yahoo.com,110: Timed out (errflg=1) in Unknown on
line 0
Notice: Unknown: Can't connect to yahoo.com,110: Timed out (errflg=1) in Unknown on
line 0
Notice: Unknown: Can't connect to yahoo.com,110: Timed out (errflg=2) in Unknown on line 0
Can anyone fix it?
Thanks.
As arkascha said, yahoo.com doesn't listen on port 110.
Yahoo's POP3 server is pop.mail.yahoo.com on port 110 (or 995 with SSL) as stated in this Yahoo help article
I have set email interception on my server.
following is my email forwarder set on server
testemail#my.server.com,"/home/server/php_pipe_mail.php"
following is my code for php_pipe_mail.php
#!/usr/bin/php -q
<?php
require_once('mimeDecode.php');
include('sql-connect.php');
error_reporting(E_ALL);
ob_start();
$raw_email = '';
if (!$stdin = fopen("php://stdin", "R"))
{
echo "ERROR: UNABLE TO OPEN php://stdin \n";
}
// ABLE TO READ THE MAIL
else
{
while (!feof($stdin))
{
$raw_email .= fread($stdin, 4096);
}
fclose($stdin);
}
$raw_email = preg_replace('/ +/', ' ', $raw_email);
var_dump($raw_email);
$buf = ob_get_contents();
$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
$params['input'] = $buf;
$params['crlf'] = "\r\n";
//Creating temp file on server
$myFile = "amail.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
fwrite($fh, $buf);
fclose($fh);
//Generating mail structure in object format
$structure = Mail_mimeDecode::decode($params);
$attachment = array();
$mail_date= date( 'Y-m-d H:i:s', strtotime($structure->headers['date']) );
$from = $structure->headers['from'];
$to = $structure->headers['to'];
$subject = htmlentities($structure->headers['subject'],ENT_QUOTES);
if($structure->ctype_primary == "multipart")
{
$body_text = $structure->parts[0]->parts[0]->body;
$body_html = $structure->parts[0]->parts[1]->body;
$x = 0;
//fetch attachment
foreach ($structure->parts as $part) {
// only save if an attachment
if (isset($part->disposition) and ($part->disposition=='attachment')) {
$attachment[$x]["filename"] = $part->d_parameters['filename'];
$attachment[$x]["content_type"] = $part->ctype_primary . "/" . $part->ctype_secondary;
$attachment[$x]["body"] = addslashes($part->body);
$x++;
}
}
}
else
{
$body_text = $structure->parts[0]->body;
$body_html = $structure->parts[1]->body;
}
$qry1 = "insert into mail_buffer(mail_date,mail_from, mail_to,mail_subject,mail_text_body,mail_html_body) Values('". $mail_date ."','".$from."','".$to."','".$subject."','".$body_text."','".$body_html."')";
mysql_query($qry1) or die(mysql_error($con));
$last_id = mysql_insert_id();
if(count($attachment) > 0)
{
for($i=0; $i < count($attachment); $i++)
{
$qry = "insert into mail_attachment(email_id,content_type, file_name,body) Values('". $last_id ."','".$attachment[$i]['content_type']."','".$attachment[$i]['filename']."','".$attachment[$i]['body']."')";
mysql_query($qry) or die(mysql_error($con));
}
}
mysql_close($con);
ob_end_clean();
?>
Now above script works perfectly fine.
I am able to fetch message header, body and attachments and can store them in database without any problems.
When email without attachments come everything works fine and email is delivered to email address I am intercepting.
But following is not working.
When email with attachments comes than email content is being stored in database but email is not delivering to email address I am intercepting and I am getting following error message in bounce back email.
A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:
pipe to |/home/server/php_pipe_mail.php
generated by testemail#my.server.com
Can anyone help me regarding the matter.
Thanks.
Could it be that, when an attachment is present, your script is echoing something? I have had problems piping emails before, and seen failure messages returned to senders, and they have been due to the piping script producing some kind of output. Maybe your error_reporting(E_ALL); is allowing the script to produce an output - try error_reporting(0);