why cant i echo imap headers subject line? php - php

Using the following class:
class Email_reader {
// imap server connection
public $conn;
// inbox storage and inbox message count
private $inbox;
private $msg_cnt;
// email login credentials
private $server = 'xxxxxxxxxxxx.com';
private $user = 'admin#xxxxxxxxx.com';
private $pass = 'xxxxxxxxx';
private $port = 143; // adjust according to server settings
// connect to the server and get the inbox emails
function __construct() {
$this->connect();
$this->inbox();
}
// close the server connection
function close() {
$this->inbox = array();
$this->msg_cnt = 0;
imap_close($this->conn);
}
// open the server connection
// the imap_open function parameters will need to be changed for the particular server
// these are laid out to connect to a Dreamhost IMAP server
function connect() {
$this->conn = imap_open('{'.$this->server.'/notls}', $this->user, $this->pass);
}
// move the message to a new folder
function move($msg_index, $folder='INBOX.Processed') {
// move on server
imap_mail_move($this->conn, $msg_index, $folder);
imap_expunge($this->conn);
// re-read the inbox
$this->inbox();
}
// get a specific message (1 = first email, 2 = second email, etc.)
function get($msg_index=NULL) {
if (count($this->inbox) <= 0) {
return array();
}
elseif ( ! is_null($msg_index) && isset($this->inbox[$msg_index])) {
return $this->inbox[$msg_index];
}
return $this->inbox[0];
}
// read the inbox
function inbox() {
$this->msg_cnt = imap_num_msg($this->conn);
$in = array();
for($i = 1; $i <= $this->msg_cnt; $i++) {
$in[] = array(
'index' => $i,
'header' => imap_headerinfo($this->conn, $i),
'body' => imap_body($this->conn, $i),
'structure' => imap_fetchstructure($this->conn, $i)
);
}
$this->inbox = $in;
}
}
And the following usage code:
$email = new Email_reader();
$msg = $email->get(1);
echo "message body is [".$msg['body']."]<br />"; //prints body //good
echo "message index is [".$msg['index']."]<br />"; //prints "2" //good
echo "message subject is [".$msg['header']->Subject."]<br />"; //prints strangness
echo "message toaddress is [".$msg['header']->toaddress."]<br />"; //prints strangeness
the attempt to print subject line prints "=?utf-8?B?TWljcm9zb2Z0IE9mZmljZSBPdXRsb29rIFRlc3QgTWVzc2FnZQ==?="
and the toaddress also something similar.
I looked at some other examples online but i dont see anything different that they do than what im doing.

You have to decode the RFC 2047 encoding of the Unicode data. Check the imap_utf8 function.

Related

How to move emails into Custom Post Type?

I found this PHP code to extract the emails. Now, I want to move this email into Custom Post type in WordPress. I have created the custom post type name as E-mail Inboxes.
Here is the code below of how I extracted the emails:
class Email_reader {
// imap server connection
public $conn;
// inbox storage and inbox message count
private $inbox;
private $msg_cnt;
// email login credentials
private $server = 'myserver.com';
private $user = 'myserver#mail.com';
private $pass = 'PASSWORD';
private $port = 993; // adjust according to server settings
// connect to the server and get the inbox emails
function __construct() {
$this->connect();
$this->inbox();
}
// close the server connection
function close() {
$this->inbox = array();
$this->msg_cnt = 0;
imap_close($this->conn);
}
// open the server connection
// the imap_open function parameters will need to be changed for the particular server
// these are laid out to connect to a Dreamhost IMAP server
function connect() {
$this->conn = imap_open('{'.$this->server.'/notls}', $this->user, $this->pass);
}
// move the message to a new folder
function move($msg_index, $folder='INBOX.Processed') {
// move on server
imap_mail_move($this->conn, $msg_index, $folder);
imap_expunge($this->conn);
// re-read the inbox
$this->inbox();
}
// get a specific message (1 = first email, 2 = second email, etc.)
function get($msg_index=NULL) {
if (count($this->inbox) <= 0) {
return array();
}
elseif ( ! is_null($msg_index) && isset($this->inbox[$msg_index])) {
return $this->inbox[$msg_index];
}
return $this->inbox[0];
}
// read the inbox
function inbox() {
$this->msg_cnt = imap_num_msg($this->conn);
$in = array();
for($i = 1; $i <= $this->msg_cnt; $i++) {
$in[] = array(
'index' => $i,
'header' => imap_headerinfo($this->conn, $i),
'body' => imap_body($this->conn, $i),
'structure' => imap_fetchstructure($this->conn, $i)
);
}
$this->inbox = $in;
}
}
$emails = new Email_reader;
echo "<pre>";
var_dump($emails);
Now I want to add this email to my WordPress Custom Post Type.
Thanks in advance.
$total = $emails->total_msg();
for ($j=1; $j <= $total; $j++) {
$mail = $emails->get($j);
$post_array = array(
'post_content' => $mail['body'],
'post_title' => $mail['header']->subject,
'post_type' => 'faqpress_email',
'post_status' => 'publish',
'meta_input' => array(
'from' => $mail['header'] ->fromaddress,
'email_date'=> $mail['header'] ->Date, // add post meta as many as you want
'ticket_id' => $mail['header']->Msgno,
),
);
wp_insert_post($post_array);
}

Unable to open socket, connection timed out

Trying to sent packages from my webhost to a game server, using this code. However it always results in Unable to open socket: Connection timed out (110) ad I can't figure out why it times out. When I try this on my localhost, it works perfectly but when on webhost, it just times out. I've tried to set the timeout to something else but it didn't help.
define("SERVERDATA_EXECCOMMAND",2);
define("SERVERDATA_AUTH",3);
class RCon {
var $Password;
var $Host;
var $Port = 27015;
var $_Sock = null;
var $_Id = 0;
function RCon ($Host,$Port,$Password) {
$this->Password = $Password;
$this->Host = $Host;
$this->Port = $Port;
$this->_Sock = #fsockopen($this->Host,$this->Port, $errno, $errstr, 30) or
die("Unable to open socket: $errstr ($errno)\n");
$this->_Set_Timeout($this->_Sock,2,500);
}
function Auth () {
$PackID = $this->_Write(SERVERDATA_AUTH,$this->Password);
// Real response (id: -1 = failure)
$ret = $this->_PacketRead();
if ($ret[1]['id'] == -1) {
die("Authentication Failure\n");
}
}
function _Set_Timeout(&$res,$s,$m=0) {
if (version_compare(phpversion(),'4.3.0','<')) {
return socket_set_timeout($res,$s,$m);
}
return stream_set_timeout($res,$s,$m);
}
function _Write($cmd, $s1='', $s2='') {
// Get and increment the packet id
$id = ++$this->_Id;
// Put our packet together
$data = pack("VV",$id,$cmd).$s1.chr(0).$s2.chr(0);
// Prefix the packet size
$data = pack("V",strlen($data)).$data;
// Send packet
fwrite($this->_Sock,$data,strlen($data));
// In case we want it later we'll return the packet id
return $id;
}
function _PacketRead() {
//Declare the return array
$retarray = array();
//Fetch the packet size
while ($size = #fread($this->_Sock,4)) {
$size = unpack('V1Size',$size);
//Work around valve breaking the protocol
if ($size["Size"] > 4096) {
//pad with 8 nulls
$packet = "\x00\x00\x00\x00\x00\x00\x00\x00".fread($this->_Sock,4096);
} else {
//Read the packet back
$packet = fread($this->_Sock,$size["Size"]);
}
array_push($retarray,unpack("V1ID/V1Response/a*S1/a*S2",$packet));
}
return $retarray;
}
function Read() {
$Packets = $this->_PacketRead();
foreach($Packets as $pack) {
if (isset($ret[$pack['ID']])) {
$ret[$pack['ID']]['S1'] .= $pack['S1'];
$ret[$pack['ID']]['S2'] .= $pack['S1'];
} else {
$ret[$pack['ID']] = array(
'Response' => $pack['Response'],
'S1' => $pack['S1'],
'S2' => $pack['S2'],
);
}
}
return $ret;
}
function sendCommand($Command) {
$Command = '"'.trim(str_replace(' ','" "', $Command)).'"';
$this->_Write(SERVERDATA_EXECCOMMAND,$Command,'');
}
function rconCommand($Command) {
$this->sendcommand($Command);
$ret = $this->Read();
//ATM: Source servers don't return the request id, but if they fix this the code below should read as
// return $ret[$this->_Id]['S1'];
return $ret[0]['S1'];
}
}
If I specify udp connection in fsockopen it does not timeout, however if I try tcp, it times out. Most likely caused by the host, but I have no idea where to go from this.
https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
https://developer.valvesoftware.com/wiki/Server_queries

PHP IMAP-Extension get clean Message-Body

I'm just experimenting a little with the IMAP-Extension for PHP and I build the connection using an object like this:
function __construct($user, $pass, $server = 'my.mailserver.ch', $port = 143) {
$this->server = $server;
$this->user = $user;
$this->pass = $pass;
$this->port = $port;
if($this->conn = imap_open('{'.$this->server.'}', $this->user, $this->pass)){
$this->success = 1;
}else{
$this->success = -1;
}
$this->inbox();
}
I then use the following function to get the neccessary data from my mails.
(Which works)
function inbox() {
$this->msg_cnt = imap_num_msg($this->conn);
$in = array();
for($i = 1; $i <= $this->msg_cnt; $i++) {
$in[] = array(
'index' => $i,
'header' => imap_headerinfo($this->conn, $i),
'body' => imap_fetchbody($this->conn, $i),
'structure' => imap_fetchstructure($this->conn, $i)
);
}
$this->inbox = $in;
}
But if I now look into the body of the message, I get multiple different things besides the message, like:
--001a113ec946082fc705210e59c7 Content-Type: multipart/alternative; boundary=001a113ec946082fc005210e59c5 --001a113ec946082fc005210e59c5 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding
And so on. I checked for ways to get a clean body from that "multipart/alternative" but I couldn't find anything that helped me. Also there are several different Content-Types in the same body.
How do I get the clean body of the message, and do I have to handle it differently for differen content-types?
Thank you for your help.

Move mail from Trash to Inbox Gmail PHP Imap

I have never played with fetching and moving emails before using IMAP and PHP, so im struggeling with moving emails that are sent to the trash back to the inbox.
Ok, so i'm fetching my emails from Gmail correctly, and i am able to delete them, or move them to trash rather.
When i try to move them back to Inbox i get the following error:
Notice: Unknown: [TRYCREATE] No folder [Gmail]/Inbox (Failure) (errflg=2) in Unknown on line 0
So obviously there is something i dont quite get, and i have been searching the web and stackoverflow for the answer the last couple of hours with no luck. Does anyone know why this particular action does not succeed?
Any help is as usual much appreciated, i would love to get the hang of this and make myself a little email app.
Below is the class i have made, see the method undo(), thats where this particular warning pops up.
class Gmail {
public $emailsexists = false;
public $emailarray = '';
private $username;
private $password;
private $inbox;
public function __construct($username,$password) {
/* connect to gmail using imap */
$hostname = '{imap.gmail.com:993/imap/ssl}INBOX';
$this->username = $username;
$this->password = $password;
/* try to connect using username and password set in core/init.php (gmail_credentials) */
$this->inbox = imap_open($hostname,$this->username,$this->password) or die('Cannot connect to Gmail: ' . imap_last_error());
}
public function delete($email) {
if ($email !== '' && is_numeric($email)) {
if (imap_mail_move($this->inbox, $email, '[Gmail]/Trash')) {
return true;
} else {
return false;
}
} else {
return false;
}
imap_close($this->inbox);
}
public function undo($email) {
if ($email !== '' && is_numeric($email)) {
if (imap_mail_move($this->inbox, $email, '[Gmail]/Inbox')) { // FIX Throws back a warning
return true;
} else {
return false;
}
} else {
return false;
}
imap_close($this->inbox);
}
public function unseen($number = false) {
/* grab emails */
$emails = imap_search($this->inbox,'UNSEEN');
/* if emails are returned, cycle through each... */
if($emails) {
/* statement that tells that emails exist */
$this->emailsexists = true;
/* put the newest emails on top */
rsort($emails);
/* Start the counter */
$x = 0;
/* Open up the accordion */
$this->emailarray.= '<div id="accordion">';
/* for every email... */
foreach($emails as $email) {
/* get information specific to this email */
$overview = imap_fetch_overview($this->inbox,$email,0);
$structure = imap_fetchstructure($this->inbox, $email);
$message = imap_fetchbody($this->inbox,$email,1,FT_PEEK);
if(isset($structure->parts) && is_array($structure->parts) && isset($structure->parts[1])) {
$part = $structure->parts[1];
$message = imap_fetchbody($this->inbox,$email,2,FT_PEEK);
}
/* escape and decode the mimeheaders */
$subject = escape(str_replace("_"," ", mb_decode_mimeheader($overview[0]->subject)));
/* decode and put the subject into the accordion header */
$this->emailarray.= '<h3>'.html_entity_decode(escape($subject)).'</h3>';
$this->emailarray.= '<div>';
$this->emailarray.= '<div class="btn-group pull-right">';
$this->emailarray.= '<span class="glyphicon glyphicon-share-alt text-success"></span>';
$this->emailarray.= '<span class="glyphicon glyphicon-send text-success"></span>';
$this->emailarray.= '<span class="glyphicon glyphicon-fire text-danger"></span>';
$this->emailarray.= '</div>';
$this->emailarray.= '<p>';
/* decode the email body using the built in quoted_printable_decode function */
$this->emailarray.= quoted_printable_decode($message);
$this->emailarray.= '</p>';
$this->emailarray.= '</div>';
/* if the counter reaches a certain number, break out and continue the script */
$x++;
if ($number) {
if ($x >= $number) {
break;
}
}
}
/* close off the accordion */
$this->emailarray.= '</div>';
/* If no emails are found return a message */
} else {
echo "No emails";
}
/* close the imap connection */
imap_close($this->inbox);
}
}
I found that if i connect to the Trash and then use an asterix to get the last message it works as intended.
public function undo($email) {
// check if message id exists and is numeric
if ($email !== '' && is_numeric($email)) {
// set hostname to trash
$hostname = '{imap.gmail.com:993/imap/ssl}[Gmail]/Trash';
$this->inbox = imap_open($hostname,$this->username,$this->password) or die('Cannot connect to Gmail: ' . imap_last_error());
// return true if the message was moved
if (imap_mail_move($this->inbox, '*', 'Inbox')) {
return true;
} else {
return false;
}
} else {
return false;
}
imap_close($this->inbox,CL_EXPUNGE);
}
Move mail INBOX To TRASH THROUGH IMAP using node-imap.
const Imap = require("imap");
const mailBox = new Imap({
host: "imap.gmail.com",
password: "password",
port: 993,
user: "email",
tls: true,
connTimeout: 30000,
authTimeout: 30000,
keepalive: false,
tlsOptions: {
rejectUnauthorized: false,
},
});
mailBox.once("error", console.error);
mailBox.once("ready", () => {
mailBox.openBox("INBOX", false, (error, box) => {
if (error) throw error;
mailBox.search(
[
// "UNSEEN",
["SUBJECT", "When to say 'sorry' at work"],
["FROM", "taco#trello.com"]
],
(error, results) => {
if (error) throw error;
console.log("results",results);
for (const uid of results) {
const mails = mailBox.fetch(uid, {
bodies: ""
// markSeen: true
});
mails.once("end", () => mailBox.end());
mails.on("message", (message, seq) => {
console.log('message',message);
message.on("body", stream => {
console.log("results123456--------",uid);
let buffer = "";
stream.on("data", chunk => (buffer += chunk.toString("utf8")));
stream.once("end", () => mailBox.move(uid, "[Gmail]/Trash"));
});
});
}
}
);
});
});
mailBox.connect();

PHP Imap reading replies in inbox

I have written/copied a script that reads emails from an inbox and updates a ticket and then moves the email to a proccessed folder. This all works perfectly on new emails to the inbox but when someone replys to an email and it ends up in the inbox my scrtipt reads nothing on the email.
Is there something different to the way an email is structured when its a reply? I need a way of reading whats in the email so I can update a ticket with the contents. Knowing which email it is to update is all taken care of its just purely reading the content Im struggling with.
Here is the code
class Email
{
// imap server connection
public $conn;
// inbox storage and inbox message count
public $inbox;
private $msg_cnt;
// email login credentials
private $server = '????????????';
private $user = '????????';
private $pass = '?????????????';
private $port = ??;
// connect to the server and get the inbox emails
function __construct()
{
$this->connect();
$this->inbox();
}
function getdecodevalue($message,$coding)
{
switch($coding) {
case 0:
case 1:
$message = imap_8bit($message);
break;
case 2:
$message = imap_binary($message);
break;
case 3:
case 5:
$message=imap_base64($message);
break;
case 4:
$message = imap_qprint($message);
break;
}
return $message;
}
// close the server connection
function close()
{
$this->inbox = array();
$this->msg_cnt = 0;
imap_close($this->conn);
}
// open the server connection
// the imap_open function parameters will need to be changed for the particular server
// these are laid out to connect to a Dreamhost IMAP server
function connect()
{
$this->conn = imap_open("{".$this->server.":".$this->port."/imap/novalidate-cert}INBOX", $this->user, $this->pass);
}
// move the message to a new folder
function move($msg_index, $folder='Read')
{
// move on server
imap_mail_move($this->conn, $msg_index, $folder);
// re-read the inbox
//$this->inbox();
}
// get a specific message (1 = first email, 2 = second email, etc.)
function get($msg_index=NULL)
{
if(count($this->inbox) <= 0)
{
return array();
}
elseif( ! is_null($msg_index) && isset($this->inbox[$msg_index]))
{
return $this->inbox[$msg_index];
}
return $this->inbox[0];
}
// read the inbox
function inbox()
{
$this->msg_cnt = imap_num_msg($this->conn);
$in = array();
for($i = 1; $i <= $this->msg_cnt; $i++)
{
$in[] = array(
'index' => $i,
'header' => imap_headerinfo($this->conn, $i),
'body' => $this->cleanBody(imap_fetchbody($this->conn, $i,1)),
'structure' => imap_fetchstructure($this->conn, $i)
);
}
$this->inbox = $in;
}
function cleanBody($body)
{
$delimiter = '#';
$startTag = '----------START REPLY----------';
$endTag = '----------END REPLY----------';
$regex = $delimiter . preg_quote($startTag, $delimiter)
. '(.*?)'
. preg_quote($endTag, $delimiter)
. $delimiter
. 's';
preg_match($regex,$body,$matches);
$ret = trim($matches[1]);
return $ret;
}
}
$emails = new Email();
$email = array();
$emailCount = 1;
foreach($emails->inbox as $ems => $em)
{
$email[$emailCount]['subject'] = $sub = $em['header']->subject;
//echo $sub;
$subParts = explode('-',$sub);
$ticketUniqueCode = trim($subParts[1]);
$sql = "SELECT * FROM ticket_main WHERE uniquecode = '".mysql_escape_string($ticketUniqueCode)."' LIMIT 1";
$query = mysql_query($sql);
if(mysql_num_rows($query))
{
$res = mysql_fetch_object($query);
$ticketBody = $em['body'];
$customerID = $res->customerID;
$sql2 = "INSERT INTO ticket_updates SET ticketID = '".$res->ticketID."' , submitted = NOW() , submittedBy = '".$res->customerID."' , message = '".mysql_escape_string($ticketBody)."' , inhouse = 0";
$query = mysql_query($sql2);
// attachment section
$message_number = $em['index'];
$attachments = array();
if(isset($em['structure']->parts) && count($em['structure']->parts))
{
//echo 'hi';
for($i = 0; $i < count($em['structure']->parts); $i++)
{
$attachments[$i] = array(
'is_attachment' => false,
'filename' => '',
'name' => '',
'attachment' => ''
);
if($em['structure']->parts[$i]->ifdparameters) {
foreach($em['structure']->parts[$i]->dparameters as $object)
{
if(strtolower($object->attribute) == 'filename')
{
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['filename'] = $object->value;
}
}
}
if($em['structure']->parts[$i]->ifparameters) {
foreach($em['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($emails->conn, $message_number, $i+1);
if($em['structure']->parts[$i]->encoding == 3)
{ // 3 = BASE64
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
}
elseif($em['structure']->parts[$i]->encoding == 4)
{ // 4 = QUOTED-PRINTABLE
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
}
}
if(isset($em['structure']->parts[$i]->disposition) && $em['structure']->parts[$i]->disposition == "attachment")
{
$filename = $attachments[$i]['name'];
$mege="";
$data="";
$mege = imap_fetchbody($emails->conn, $message_number, $i+1);
$filename= $filename;
$fp=fopen('???????????????'.$filename,"w");
$data=$emails->getdecodevalue($mege,$em['structure']->parts[$i]->type);
fputs($fp,$data);
fclose($fp);
$email[$emailCount]['attachment'] = $attachments;
}
}
}
}
$emailCount++;
}
$emailNumbers = imap_search($emails->conn,'ALL');
if(!empty($emailNumbers))
{
foreach($emailNumbers as $a)
{
$emails->move($a);
}
imap_expunge($emails->conn);
}
$emails->close();
Hope that makes some sense and someone can actually help.
Many many thanks in advance
Jon
Well the most obvious thing is your code assumes a message is always in part 1, your line:
'body' => $this->cleanBody(imap_fetchbody($this->conn, $i,1)),
Means it's only looking at body 1. If it's a pure text email body 1 will be right, but if it's multipart/alternative (text & html) body 1 would be the base MIME message which tells you that there are sub bodies (body 1.1, 1.2) that actually contain the content.
Further if the reply includes embedded images, or includes the message it's replying to as an attachment then you could have even more bodies/locations.
So how do I find the body? (you ask)... well you can use imap_fetchstructure to learn about all the body parts, then search through it to find a piece with type=0 (text) and then download that body part. (The first found text should be the right one, but note there could be more than one text body type in an email).

Categories