Wednesday 29 July 2015

Creating your own mail application in PHP

First time when you read the title of this post, You will get surprised. But believe me its very simple in PHP. For that purpose there is a library in php known as IMAP.

Connection to IMAP

To establish a connection to the IMAP server, we use the imap_connect() function as shown here:
<?php
$imap = imap_open($mailboxPath, $username, $password);
?>

The mailbox path, username, and password strings are required parameters to connect to the server. You can learn about the optional parameters in the manual.

The mailbox path is a string that identifies server and port information in braces followed by the name of the desired mail folder. Here are a few strings for the inbox folder for popular mail providers:

Gmail {imap.gmail.com:993/imap/ssl}INBOX
Yahoo {imap.mail.yahoo.com:993/imap/ssl}INBOX
AOL {imap.aol.com:993/imap/ssl}INBOX

Some servers do not have SSL enabled, in which case you would omit “SSL” from the string. Other servers might use self-signed certificates, in which you would include “novalidate-cert”.

<?php
$imap = imap_open("{localhost:993/imap/ssl/novalidate-cert}", "username", "password");
?>

Listing the Folders

Inbox, sent, trash, and spam folders are seen in pretty much every email account, and users can often create custom folders as well. In order to view messages in these folders, we need to change our connection string. For example, I used “INBOX” in the path string earlier. If I wanted to connect to the spam folder, I might want to use something like “Spam” instead. But even though it might be listed as Spam in your email account when viewed through a mail client, the real folder name might be different behind the scenes. We can list all of the available folders in an account using imap_list().

<?php
$folders = imap_list($imap, "{imap.gmail.com:993/imap/ssl}", "*");
echo "<ul>";
foreach ($folders as $folder) {
    $folder = str_replace("{imap.gmail.com:993/imap/ssl}", "", imap_utf7_decode($folder));
    echo '<li><a href="mail.php?folder=' . $folder . '&func=view">' . $folder . '</a></li>';
}
echo "</ul>";
?>
We have to pass the connection handle obtained with imap_open() as the initial parameter to imap_list(). We also need to pass a bare path sting (without the folder, e.g. “INBOX”). The star as the third parameter requests all of the available folders.

Mail Script(mail.php)

Just paste the code I will explain one by one...

<?php

//Here receiving all values here so that will use in all functions

$func = (!empty($_GET["func"])) ? $_GET["func"] : "view";
$folder = (!empty($_GET["folder"])) ? $_GET["folder"] : "INBOX";
$uid = (!empty($_GET["uid"])) ? $_GET["uid"] : 0;
$no=(!empty($_GET["no"])) ? $_GET["no"] : 0;
$part=(!empty($_GET["part"])) ? $_GET["part"] : 0;
$enc=(!empty($_GET["enc"])) ? $_GET["enc"] : 0;
$path='';

//username and password of mail. In the server name portion just paste your server name. if you want to fetch google mail you have to get SSL certified server. 

$username = 'usernamehere';
$password = 'passwordhere';
$imap = imap_open("{servername:143/novalidate-cert}".$folder,$username,$password);

// Checking which is the called function 

switch ($func) {
    case "delete":
        deleteMail($imap, $folder, $uid);
        break;

    case "read":
        readMail($imap, $folder, $uid,$no);
        break;

     case "download":
     downloadAttachment($imap, $uid, $part, $enc, $path);  

    case "view":
    default:
        viewMail($imap, $folder);
        break;

       
}

// function to read all mails in corresponding folder. If the folder is inbox it will list all emails in the Inbox folder.

function viewMail($imap, $folder){


     $numMessages = imap_num_msg($imap);
    $k=0;
for ($i = 0; $i <= $numMessages; $i++) {
  
  if($numMessages>$k){
    $header = imap_header($imap, $i);
if(isset($header->from[0])){
    $fromInfo = $header->from[0];
}
if(isset($header->reply_to[0])){
    $replyInfo = $header->reply_to[0];
}
    $details = array(
        "fromAddr" => (isset($fromInfo->mailbox) && isset($fromInfo->host))
            ? $fromInfo->mailbox . "@" . $fromInfo->host : "",
        "fromName" => (isset($fromInfo->personal))
            ? $fromInfo->personal : "",
        "replyAddr" => (isset($replyInfo->mailbox) && isset($replyInfo->host))
            ? $replyInfo->mailbox . "@" . $replyInfo->host : "",
        "replyName" => (isset($replyTo->personal))
            ? $replyto->personal : "",
        "subject" => (isset($header->subject))
            ? $header->subject : "",
        "udate" => (isset($header->udate))
            ? $header->udate : ""
    );

    $uid = imap_uid($imap, $i);

    echo "<ul>";
    echo "<li><strong>From:</strong>" . $details["fromName"];
    echo " " . $details["fromAddr"] . "</li>";
    echo "<li><strong>Subject:</strong> " . $details["subject"] . "</li>";
    echo '<li><a href="mail.php?folder=' . $folder . '&uid=' . $uid . '&func=read&no='.$i.'">Read</a>';
    echo " | ";
    echo '<a href="mail.php?folder=' . $folder . '&uid=' . $uid . '&func=delete">Delete</a></li>';
    echo "</ul>";
$k++;
}
}
}

//This will delete the correspond mail with UID

function deleteMail($imap, $folder, $uid){

    imap_delete($imap, $uid, FT_UID);
imap_expunge($imap);
}

//This function will read corresponding mail.it will display the mail content and fetch the attachment also

function readMail($imap, $folder, $uid,$no){
$func='download';
    echo $gh=getBody($uid,$imap);
       $mailStruct = imap_fetchstructure($imap, $no);
       print_r($mailStruct);
$attachments = getAttachments($imap, $no, $mailStruct, "");
//print_r($attachments);

echo "Attachments: ";
foreach ($attachments as $attachment) {

echo '<a href="mail.php?func=' . $func . '&folder=' . $folder . '&uid=' . $uid .
    '&part=' . $attachment["partNum"] . '&enc=' . $attachment["enc"] . '">' .
    $attachment["name"] . "</a>";
}
}

//This function is called inside read mail. Here it will read the attachment details of the mail. if nothing is their will send null

function getAttachments($imap, $mailNum, $part, $partNum) {
    $attachments = array();

    if (isset($part->parts)) {
        foreach ($part->parts as $key => $subpart) {
            if($partNum != "") {
                $newPartNum = $partNum . "." . ($key + 1);
            }
            else {
                $newPartNum = ($key+1);
            }
            $result = getAttachments($imap, $mailNum, $subpart,
                $newPartNum);
            if (count($result) != 0) {
                 array_push($attachments, $result);
             }
        }
    }
    else if (isset($part->disposition)) {
        if ($part->disposition == "attachment") {
            $partStruct = imap_bodystruct($imap, $mailNum,
                $partNum);
            $attachmentDetails = array(
                "name"    => $part->dparameters[0]->value,
                "partNum" => $partNum,
                "enc"     => $partStruct->encoding
            );
            return $attachmentDetails;
        }
    }

    return $attachments;
}

//This function is used to download attachments from the mail.It is called in read mail function

function downloadAttachment($imap, $uid, $partNum, $encoding, $path) {
    $partStruct = imap_bodystruct($imap, imap_msgno($imap, $uid), $partNum);

    $filename = $partStruct->dparameters[0]->value;
    $message = imap_fetchbody($imap, $uid, $partNum, FT_UID);

    switch ($encoding) {
        case 0:
        case 1:
            $message = imap_8bit($message);
            break;
        case 2:
            $message = imap_binary($message);
            break;
        case 3:
            $message = imap_base64($message);
            break;
        case 4:
            $message = quoted_printable_decode($message);
            break;
    }

    header("Content-Description: File Transfer");
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=" . $filename);
    header("Content-Transfer-Encoding: binary");
    header("Expires: 0");
    header("Cache-Control: must-revalidate");
    header("Pragma: public");
    echo $message;
}

//Function used to get details of body part in the mail


function getBody($uid, $imap) {
    $body = get_part($imap, $uid, "TEXT/HTML");
    // if HTML body is empty, try getting text body
    if ($body == "") {
        $body = get_part($imap, $uid, "TEXT/PLAIN");
    }
    return $body;
}

function get_part($imap, $uid, $mimetype, $structure = false, $partNumber = false) {
    if (!$structure) {
           $structure = imap_fetchstructure($imap, $uid, FT_UID);
    }
    if ($structure) {
        if ($mimetype == get_mime_type($structure)) {
            if (!$partNumber) {
                $partNumber = 1;
            }
            $text = imap_fetchbody($imap, $uid, $partNumber, FT_UID);
            switch ($structure->encoding) {
                case 3: return imap_base64($text);
                case 4: return imap_qprint($text);
                default: return $text;
           }
       }

        // multipart 
        if ($structure->type == 1) {
            foreach ($structure->parts as $index => $subStruct) {
                $prefix = "";
                if ($partNumber) {
                    $prefix = $partNumber . ".";
                }
                $data = get_part($imap, $uid, $mimetype, $subStruct, $prefix . ($index + 1));
                if ($data) {
                    return $data;
                }
            }
        }
    }


    return false;
}
//Function will identify the mime type of the mail

function get_mime_type($structure) {
    $primaryMimetype = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");

    if ($structure->subtype) {
       return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype;
    }
    return "TEXT/PLAIN";
}

?>