Sunday 9 December 2018

PHP EmailMessage class for extracting attachments

Hi, recently I had to create a php program which fetches emails with attachments (including inline). I searched a lot and succeeded with help of :

https://www.electrictoolbox.com/php-email-extract-inline-image-attachments/
https://www.electrictoolbox.com/php-email-message-class-extracting-attachments/

Though i had to make some changes in the EmailMessage.php to make it work. I am uploading the same file with some necessary changes.

Steps to run the program :
1. Download EmailMessageFinal.php.
2. Enter the email id you want to fetch mails from , in the $login variable at line 31.
     Enter password just below it in the $password variable.
     At line 40, enter the emailUID you want to fetch, you can try setting it to 1 and then change it to any emailUID when you get a hold of it.

3. Just run the php file with WampServer or XAMPP or any software of your choice.

The brower should fetch the email and display it in the same browser window, along with attachments (including inline images) like this :

I am grateful to electricToolBox for sharing this awesome code with us.

I know the presentation of program is very rough. But i hope it helps you do the core part and build the decorations yourself.


Here is the code in EmailMessageFinal.php :

<?php
if (!file_exists("debug/")) {
    $oldmask = umask(0);
    mkdir("debug/", 0777, true);
    umask($oldmask);
}
if (!file_exists("email_files/Inlineimages/")) {
    $oldmask = umask(0);
    mkdir("email_files/Inlineimages/", 0777, true);
    umask($oldmask);
}
if (!file_exists("email_files/attachments/")) {
    $oldmask = umask(0);
    mkdir("email_files/attachments/", 0777, true);
    umask($oldmask);
}


// server needs to be full server connection string, as in the example below
// $server = '{imap.gmail.com:993/ssl/novalidate-cert}';
// another example
// $server = '{pop3.example.com:110/pop3}';
$server = '{imap.gmail.com:993/imap/ssl/novalidate-cert}Inbox';
// $serverPOP = '{pop.gmail.com:995/pop3/ssl}Inbox';
// and put your login and password here
/* $login = 'geniusunil1@gmail.com';
$password = 'Boomba2410'; */
$login = 'dummy@gmail.com';
$password = 'dummy';
/* $login = 'geniusunil1@gmail.com';
$password = 'Boomba2410'; */

$connection = imap_open($server, $login, $password);
$emailUID = 25122;//24722;
//$msgno = imap_msgno();
// the number in constructor is the message number
$emailMessage = new EmailMessage($connection,$emailUID);
// set to true to get the message parts (or don't set to false, the default is true)
// $emailMessage->getAttachments = false;
$message=$emailMessage->fetch();
// echo $message;
// print_r($emailMessage->attachments);
preg_match_all('/src="cid:(.*)"/Uims', $emailMessage->bodyHTML, $matches);
// if there are any matches, loop through them and save to filesystem, change the src property
// of the image to an actual URL it can be viewed at
// print_r($matches);
if(count($matches[1])) {
// search and replace arrays will be used in str_replace function below
$search = array();
$replace = array();
foreach($matches[1] as $match) {
// work out some unique filename for it and save to filesystem etc
$uniqueFilename = $emailMessage->attachments[$match]['filename'];
// change /path/to/images to actual path
// $uniqueFilename = "a";
// echo $uniqueFilename;
file_put_contents("email_files/Inlineimages/".$uniqueFilename, $emailMessage->attachments[$match]['data']);
$search[] = "src=\"cid:$match\"";
// change www.example.com etc to actual URL
$replace[] = "src=\"email_files/Inlineimages/$uniqueFilename\"";
}
// now do the replacements
$emailMessage->bodyHTML = str_replace($search, $replace, $emailMessage->bodyHTML);
$message=$emailMessage->bodyHTML;
}
echo "message : ".$message;
$emailMessage->saveAndAttachments();
// $emailMessage->showAttachments();
imap_close($connection);
exit;



class EmailMessage {
protected $connection;
protected $messageNumber;
protected $dates;
protected $emails;
protected $message;
public $bodyHTML = '';
public $bodyPlain = '';
public $attachments;
public $getAttachments = true;
public function __construct($connection, $messageNumber) {
$this->connection = $connection;
/* $this->dates = date("d M Y", strToTime("-6 days"));
$this->emails = imap_search($this->connection, "SINCE \"$this->dates\"", SE_UID);
rsort($this->emails); */
$this->messageNumber = imap_msgno($this->connection,$messageNumber);
}
public function fetch() {
$structure = imap_fetchstructure($this->connection, $this->messageNumber);
file_put_contents("debug/structure.txt", "Structure \n" . date("Y-m-d h:i:sa") . "\n" . print_r($structure, true) . PHP_EOL); //
if(!$structure) {
return false;
}
else {
if(isset($structure->parts))
$this->message= $this->recurse($structure->parts);
else{
$part=$structure;
$structure->parts = Array($part);
$this->message= $this->recurse($structure->parts);
/* if($part->subtype == 'PLAIN') {
$this->bodyPlain .= $this->getPart(1, $part->encoding);
$this->message = $this->bodyPlain;
}
else {
$this->bodyHTML .= $this->getPart(1, $part->encoding);
$this->message = $this->bodyHTML;
} */
/* if ($part->ifdisposition == 0) {
if($part->subtype == 'PLAIN') {
$this->bodyPlain .= $this->getPart(1, $part->encoding);
$this->message = $this->bodyPlain;
}
else {
$this->bodyHTML .= $this->getPart(1, $part->encoding);
$this->message = $this->bodyHTML;
}
} else {
// $attachment = getPart($connection, $messageNumber, $partNumber, $part->encoding);
//get the attachment
} */
}
return $this->message;
}
}
public function recurse($messageParts, $prefix = '', $index = 1, $fullPrefix = true) {
foreach($messageParts as $part) {
$partNumber = $prefix . $index;
if($part->type == 0) {
if(isset($part->ifdisposition)){
if($part->ifdisposition == 1 && $part->disposition == 'ATTACHMENT'){
$this->attachments[] = array(
'type' => $part->type,
'subtype' => $part->subtype,
'filename' => $this->getFilenameFromPart($part),
'data' => $this->getAttachments ? $this->getPart($partNumber, $part->encoding) : '',
'inline' => false,
);

}
else {
if ($part->subtype == 'PLAIN') {
$this->bodyPlain .= nl2br($this->getPart($partNumber, $part->encoding));
$this->message = $this->bodyPlain;
// echo $this->message;
} else {
$this->bodyHTML .= $this->getPart($partNumber, $part->encoding);
$this->message = $this->bodyHTML;
}
}
}
else {
if ($part->subtype == 'PLAIN') {
$this->bodyPlain .= $this->getPart($partNumber, $part->encoding);
$this->message = $this->bodyPlain;
} else {
$this->bodyHTML .= $this->getPart($partNumber, $part->encoding);
$this->message = $this->bodyHTML;
}
}


}
elseif($part->type == 2) {
$msg = new EmailMessage($this->connection, $this->messageNumber);
$msg->getAttachments = $this->getAttachments;
$msg->recurse($part->parts, $partNumber.'.', 0, false);
$this->attachments[] = array(
'type' => $part->type,
'subtype' => $part->subtype,
'filename' => '',
'data' => $msg,
'inline' => false,
);
}
elseif(isset($part->parts)) {
if($fullPrefix) {
$this->recurse($part->parts, $prefix.$index.'.');
}
else {
$this->recurse($part->parts, $prefix);
}
}
elseif($part->type > 2) {
if(isset($part->disposition)) {
if($part->disposition == 'INLINE' && $part->type == 5){
$id = str_replace(array('<', '>'), '', $part->id);
$this->attachments[$id] = array(
'type' => $part->type,
'subtype' => $part->subtype,
'filename' => $this->getFilenameFromPart($part),
'data' => $this->getAttachments ? $this->getPart($partNumber, $part->encoding) : '',
'inline' => true,
);
}
else{
$this->attachments[] = array(
'type' => $part->type,
'subtype' => $part->subtype,
'filename' => $this->getFilenameFromPart($part),
'data' => $this->getAttachments ? $this->getPart($partNumber, $part->encoding) : '',
'inline' => false,
);
}
}
else{
$id = str_replace(array('<', '>'), '', $part->id);
$this->attachments[$id] = array(
'type' => $part->type,
'subtype' => $part->subtype,
'filename' => $this->getFilenameFromPart($part),
'data' => $this->getAttachments ? $this->getPart($partNumber, $part->encoding) : '',
'inline' => true,
);
}
}
$index++;
}
return $this->message;
}
function getPart($partNumber, $encoding) {
$data = imap_fetchbody($this->connection, $this->messageNumber, $partNumber);
switch($encoding) {
case 0: return $data; // 7BIT
case 1: return $data; // 8BIT
case 2: return $data; // BINARY
case 3: return base64_decode($data); // BASE64
case 4: return quoted_printable_decode($data); // QUOTED_PRINTABLE
case 5: return $data; // OTHER
}

}
function getFilenameFromPart($part) {
$filename = '';
if($part->ifdparameters) {
foreach($part->dparameters as $object) {
if(strtolower($object->attribute) == 'filename') {
$filename = $object->value;
}
}
}
if(!$filename && $part->ifparameters) {
foreach($part->parameters as $object) {
if(strtolower($object->attribute) == 'name') {
$filename = $object->value;
}
}
}
return $filename;
}
public function saveAndAttachments(){
if(isset($this->attachments)){
foreach ($this->attachments as $attachment) {
// echo "there are attachments";
// print_r($attachment);
if ($attachment['inline'] != true) {
echo "there are attachments";
// echo 'email_files/attachments/'.$attachment['filename'].'did it work:?';
file_put_contents('email_files/attachments/' . $attachment['filename'], $attachment['data']);
echo "<embed src=\"". "email_files/attachments/" . $attachment['filename'] ."\"/>";
}

}
}
}
/* public function showAttachments(){
if(isset($this->attachments)){
foreach ($this->attachments as $attachment) {
if ($attachment['inline'] == false) {
file_put_contents('email_files/attachments/' . $attachment['filename'], $attachment['data']);
}
}
}
} */
}

Sunday 30 April 2017

Screen does not sleep with time in Android - Solution

Ever noticed that your Android smartphone screen is never sleeping no matter what the setting is?
If yes, this post might be of your use.
What i found is that it happens because of  an app which is designed to keep the screen awake while the app is active. The app can be anyone among your installed apps.
The problem is that these apps keep the screen awake even when they are in background.

Quick Solution :
First ensure that in Settings - Display - Sleep, you have set the desired time for sleep.
After that just remove every single app from the background (recent screens).

This is easy, but if you want to know which app is the culprit in your case, you will have to check that by hit and trial method. Just remove the apps one by one and see if that solves your problem.

In my case, it was a game called LONEWOLF.

Solution tried and tested with : Moto G3, Android 6.0.1

Sunday 28 August 2016

Bluestacks Vs. LeapDroid, which is better?

Recently the market has filled up with a lots of new and great Android Emulators. This has challenged the monopoly of Bluestacks. Also i believe that there are now some emulators which beat Bluestacks easily. Here i am explaining how LeapDroid (another free great emulator) is better than  Bluestacks.

1. LeapDroid is Faster
     LeapDroid boots up faster than Bluestacks.

2. LeapDroid gives you better storage space
    In LeapDroid you can use up all the free hard disk space in the emulator.

3. Bloatwares
    LeadDroid won't force you to install any app or game while Bluestacks will do that daily.

4. Reliability
     I used both emulators and sometimes Bluestacks even refuses to start for days, such a problem has never occurred to me with LeapDroid.

5. No crashes
     Bluestacks crashes on my machine every 10 minutes when i use an app continuously but no such problem occurs with LeapDroid.


LeapDroid has given me a completely better experience.
Also you might wanna know how to transfer files between LeapDroid and Windows host using shared folder between the host and the Android VM.






Friday 11 December 2015

Remove write protection from your pen drive

Sometimes, your pen drive goes write-protected all of a sudden. 
In this situation, you can not delete or write anything on the flash drive. You cannot even format your own flash drive.

This might happen because of virus, hardware switch or some other reason.
Another fact out of my experience is that hoping to solve the problem with linux distro will not help. The problem persists on every OS.

Solution
makeuseof has given it a good shot.
First try those steps on the makeuseof blog, but if they do not work, don't be upset because i have a couple of more ideas to try.

1. Look for the recovery tools provided by the manufacturer of the flash drive
    eg. Transcend : http://in.transcend-info.com/Support/Software-3/ (it worked for me)
2. If it is covered in warranty, return/replace it.
3. Try mUsbFixer from http://musbfixer.in/

Tried on : Transcend flash drive 8GB
May work with : other flash drives
    

Thursday 3 September 2015

Display battery percentage level indicator on Android Lollipop (without root)

I am a cyanogenmod fan because i love how customizable it is at every aspect. Well, since i have got a new phone now (moto g3 2015), i have to stay away from cyanogenmod for at least a while for two reasons :
  1. Rooting my phone will void the warranty. 
  2. There is not yet any stable Cyanogenmod ROM available.
Due to this i am struggling with many customization tasks. One of them is the battery level indicator. I want it to display battery level in form of percentage but no option for that has been provided in the stock OS of my Moto G 2015. I reached out for a method to achieve battery percentage indicator (without rooting) and found many which i am gonna share with you :

The best one is Battery Percentage.


1. Full Battery & Theft Alarm
  Features :
  • SMART WATCH integration
  • BATTERY PERCENTAGE
  • Sound and vibration alarm when charger is unplugged. (Anti theft alarm)
  • Full battery alarm
   Pros :
  • Loads of features.
   Cons :
  • Always takes the space of a notification in the drop down space of android 
2. Battery Percentage
   Features :
  • Status bar icon 
   Pros :
  • Simple and small 
   Cons :
  • No additional features 
  • Always takes the space of a notification in the drop down space of android 

2. Batteryminder

    Features :
  •      Customizable status Bar Icon 
  •      Tells the temperature 
  •      Alerts for low battery and fully charged battery 
  •      Widget available 

    Pros :
  • Additional features like alerts for low or full battery 
  • Widget available 

    Cons :
  • Always takes the space of a notification in the drop down space of android. 

3. Battery Widget Reborn (Free)

Features :
  • Highly customizable status icon. 
  • Additional toggles for wifi bluetooth etc. 
  • Motorola 1% hack 
  • Customizable widget option 

Pros :
  • High customizability and many features 

Cons :
  • Always takes the space of a notification in the drop down space of android. 

4. Battery Percent Enabler :

Features :
  • Displays battery percentage within the stock battery icon 
  • Does not require root. 

Pros :
  • Most desirable feature 
  • Does not occupy the notification area 

Cons :
  • Zero customizability 
  • Very small text (hardly readable) 
  • Text does not show when battery is charging 

Battery Percent Enabler could be the best choice only if it could eliminate its cons listed above.

Tested with : Moto G3 2015, Android 5.1.1
May also work with : Any Android Phone

Monday 13 April 2015

Remove Saleplus malware completely without any anti-malware

SalePlus
SalePlus adware
Recently my laptop got infected by the Saleplus adware/malware from a website. Symptoms are :
1. You see ads on every page you visit even when you have the Adblock Plus installed.
SalePlus ads
SalePlus ads

Saleplus adblock
SalePlus ads even with adblock plus enabled

2. Biased Google search results.
SalePlus google
Expected search results
Saleplus google
Search results altered by SalePlus


3. Slow internet speed.

In my case, only Google chrome was the affected browser. Hence following are the steps to remove it from Google chrome and Windows only. ...

How to get rid of it.....
  1. Uninstall SalePlus from Windows installed Program and features.
    To achieve this in windows 7, press windows button --> Control Panel --> Programs --> Uninstall a Program. After that find "SalePlus" and uninstall it. For other windows versions, steps are almost similar.
  2. Remove it from startup of WIndows.
    Press windows button and type "msconfig", hit enter.
    Goto the Startup and look for suspicious entries. Generally the adware takes the name of whatever file you were trying to download from the infected website. e.g. in my case it was "Eluveitie - The Call of the Mountains".
    Disable such suspicious startup programs. Do not close the window yet.
    Saleplus startup
    Remove SalePlus from startup

    1. Delete its files and folders
      Have a look at its location in the same table in msconfig (previous step) and go to that location i.e. go to "C:\Users\code\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\Eluveitie - The Call of the Mountains".
      Right click on the shortcut "Eluveitie - The Call of the Mountains" ---> properties.
      Note down the value in target field and go to that address. e.g. go to "C:\ProgramData\{82d33535-da55-b0aa-82d3-33535da5d4d7}" and delete "{82d33535-da55-b0aa-82d3-33535da5d4d7}" from C:\ProgramData. Also delete the shortcut you found earlier at "C:\Users\code\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\Eluveitie - The Call of the Mountains".
    2. Delete C:\ProgramData\4288546593436265821 (or similar folder with date modified same as other two folders in step 2 and step 3.)
    3. Remove the SalePlus extension from Google Chrome.
      Visit chrome://extensions/ (just paste this in chrome address bar)  and enable developer mode.
      Search for SSalePlus and check the "Loaded from: " attribute of the extension. This is the address which allows it to rise from ashes even when you delete the extension from chrome. In my case it is located at C:\ProgramData\ambmpnbogdlmjcmpeejljnhbnmojogeh.
      Delete this directory "ambmpnbogdlmjcmpeejljnhbnmojogeh".
      Also disable and and remove the extension from Google chrome.
      Saleplus chrome
      Saleplus chrome extension

    4. Now close msconfig window from step 2 and restart.
    Now the annoying ads must be gone. All the best.
    Tried on : Windows 7, Google chrome Version 41.0.2272.118 dev-m
    May also work for : Any version of windows, Other browsers

    Tuesday 7 April 2015

    5 important steps to optimize the speed of your Wordpress website


    I am a Wordpress developer. I tried to optimize the speed of my Wordpress website. After hours of searching i found solutions but most of them didn't work for me. Then i thought, why not try combining some of the working solutions?.. I must tell, the website i was working on was created on Genesis Framework which is the fastest among all the themes we generally use for our websites.
    I will share how i optimized the speed of my Wordpress website.
    Let us jump to the steps without wasting much of your precious time.

    1. Reduce the size of all your images by compressing them, you'll get some online image compressors. Replace .png images with .jpg if possible because a png image increases the server response time which leads to slow pages. One of the online image compressors is :
    http://compresspng.com/

    2. Try and use minimum javaScript in your website. If you have to use js anyway, put all your js in footer after </body> tag because web pages use top to bottom approach, else it loads the js first and then the content, due to which none of the above-the-fold content(html) on your page may be rendered.
    You can also call your js asynchronously by using async (suggested by google's pagespeed insights ).
    Most of us do not know what exactly calling the js "asynchronously" means. Well according to what i understood after applying async is that your js will load along with your page but it will not block the above-the-fold content.

    3.Try and use background colors instead of images.

    4. Add this code to your .htacess file
    # BEGIN Compress text files
    <ifModule mod_deflate.c>
      AddOutputFilterByType DEFLATE text/html text/xml text/css text/plain
      AddOutputFilterByType DEFLATE image/svg+xml application/xhtml+xml application/xml
      AddOutputFilterByType DEFLATE application/rdf+xml application/rss+xml application/atom+xml
      AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript application/json
      AddOutputFilterByType DEFLATE application/x-font-ttf application/x-font-otf
      AddOutputFilterByType DEFLATE font/truetype font/opentype
    </ifModule>
    # END Compress text files
    # BEGIN Expire headers
    <ifModule mod_expires.c>
      ExpiresActive On
      ExpiresDefault "access plus 300 seconds"
      ExpiresByType image/x-icon "access plus 2592000 seconds"
      ExpiresByType image/jpeg "access plus 2592000 seconds"
      ExpiresByType image/png "access plus 2592000 seconds"
      ExpiresByType image/gif "access plus 2592000 seconds"
      ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
      ExpiresByType text/css "access plus 604800 seconds"
      ExpiresByType text/javascript "access plus 216000 seconds"
      ExpiresByType application/javascript "access plus 216000 seconds"
      ExpiresByType application/x-javascript "access plus 216000 seconds"
      ExpiresByType text/html "access plus 600 seconds"
      ExpiresByType application/xhtml+xml "access plus 600 seconds"
    </ifModule>
    # END Expire headers
    # BEGIN Cache-Control Headers
    <ifModule mod_headers.c>
      <filesMatch ".(ico|jpe?g|png|gif|swf)$">
        Header set Cache-Control "public"
      </filesMatch>
      <filesMatch ".(css)$">
        Header set Cache-Control "public"
      </filesMatch>
      <filesMatch ".(js)$">
        Header set Cache-Control "private"
      </filesMatch>
      <filesMatch ".(x?html?|php)$">
        Header set Cache-Control "private, must-revalidate"
      </filesMatch>
    </ifModule>
    # END Cache-Control Headers
    # BEGIN Turn ETags Off
    FileETag None
    # END Turn ETags Off# Leverage Browser Caching Ninja -- Starts here
    # Do not write anything between "Leverage Browser Caching Ninja -- Starts" and "Leverage Browser Caching Ninja -- Ends"
    # It will be deleted while uninstalling Leverage Browser Caching Ninja plugin
    <IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
    ExpiresByType image/x-icon "access plus 1 year"
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/jpg "access plus 1 month"
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType text/css "access 1 month"
    ExpiresByType application/javascript "access plus 1 year"
    </IfModule>
    # Leverage Browser Caching Ninja -- Ends here
    The above code will do the following :
    i) Compress text files
    ii) Enable Cache control headers
    iii) Enable Expire Headers
    iv) Enable Leverage Browser caching Ninja

    5. If you still do not get the desired speed, you may want to minify your css and js as suggested by google page speed insights.
    These five steps got me an optimized website :). Good luck for yours....

    Tried on : Wordpress 4.1
    May work on : Any other Wordpress version

    Google+

    Featured Post

    PHP EmailMessage class for extracting attachments

    Hi, recently I had to create a php program which fetches emails with attachments (including inline). I searched a lot and succeeded with h...