Monday, November 21, 2016

Java read email from google using oauth2 and parse email

Read Email From Google Account


package com.google_api;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by pritom on 21/11/2016.
 */
public class JavaReadEmail extends JavaRawEmailParser {
    public static void main(String[] args) throws Exception {
        String accessToken = getAccessToken();
        String userID = "118224582562607576118"; /* From google profile */
        String messageID = "158855e85a035ed1";
        String url = "https://www.googleapis.com/gmail/v1/users/";
        url += userID + "/messages/" + messageID + "?format=raw";
        url += "&access_token=" + accessToken;

        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Content-Type", "application/json");

        int httpCode = connection.getResponseCode();
        String responseMessage = connection.getResponseMessage(), httpResponse = "";
        InputStream is = null;
        if (httpCode >= 200 && httpCode <= 299) {
            is = connection.getInputStream();
        }
        else {
            is = connection.getErrorStream();
        }

        Writer writer5 = new StringWriter();
        char[] buffer = new char[1024];
        Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        int n;
        while ((n = reader.read(buffer)) != -1) {
            writer5.write(buffer, 0, n);
        }
        httpResponse = writer5.toString();
        println(httpResponse);

        String snippet = httpResponse.substring(httpResponse.indexOf("\"snippet\":") + 12);
        snippet = snippet.substring(0, snippet.indexOf("\n") - 2).trim();
        println("Snippet=" + snippet);

        String raw = httpResponse.substring(httpResponse.indexOf("\"raw\":") + 8);
        raw = raw.substring(0, raw.indexOf("\n") - 2).trim();

        parse(raw);
    }

    private static String getAccessToken() throws Exception {
        return "return access token from google";
    }
}

Parse Email Received From Google Account


package com.google_api;

import javax.mail.*;
import javax.mail.internet.MimeMessage;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.util.*;

/**
 * Created by pritom on 20/11/2016.
 */
public class JavaRawEmailParser {
    private static final String ENCODING = "UTF-8";

    public static void parse(String rawEmail) throws Exception {
        rawEmail = Base64Decoder.decodeBase64(rawEmail);
        Session s = Session.getDefaultInstance(new Properties());
        InputStream is = new ByteArrayInputStream(rawEmail.getBytes(ENCODING));
        MimeMessage mimeMessage = new MimeMessage(s, is);
        Enumeration enumeration = mimeMessage.getAllHeaders();
        while (enumeration.hasMoreElements()) {
            Header header = (Header) enumeration.nextElement();
            if (!header.getName().contains("Received")) {
                println(header.getName() + " == " + toSingleLine(header.getValue()));
            }
        }
        Map output = processMultipart((Multipart) mimeMessage.getContent());
        for (Object key : output.keySet().toArray()) {
            println("Key=<<" + key + ">> == " + output.get(key));
        }
    }

    private static Map processMultipart(Multipart multipart) throws Exception {
        Map output = new HashMap();
        output.put("html", "");
        output.put("text", "");
        List attachments = new ArrayList();

        for(int i = 0; i < multipart.getCount(); i++) {
            Map result = processBodyPart(multipart.getBodyPart(i));
            if (result != null) {
                if (result.containsKey("type")) {
                    if (result.get("type").toString().equalsIgnoreCase("html")) {
                        output.put("html", result.get("content").toString());
                    }
                    else if (result.get("type").toString().equalsIgnoreCase("text")) {
                        output.put("text", result.get("content").toString());
                    }
                    else if (result.get("type").toString().equalsIgnoreCase("attachment")) {
                        attachments.add(result);
                    }
                }
                if (result.containsKey("html")) {
                    output.put("html", result.get("html").toString());
                }
                if (result.containsKey("text")) {
                    output.put("text", result.get("text").toString());
                }
                if (result.containsKey("attachments")) {
                    List thisAttachments = (List) result.get("attachments");
                    for (int i2 = 0; i2 < thisAttachments.size(); i2++) {
                        attachments.add(thisAttachments.get(i2));
                    }
                }
            }
        }
        output.put("attachments", attachments);

        return output;
    }

    private static Map processBodyPart(BodyPart bodyPart) throws Exception {
        if(bodyPart.isMimeType("text/html") && bodyPart.getFileName() == null) {
            Map data = new HashMap();
            data.put("type", "html");
            data.put("content", bodyPart.getContent().toString());
            return data;
        }
        else if(bodyPart.isMimeType("text/plain") && bodyPart.getFileName() == null) {
            Map data = new HashMap();
            data.put("type", "text");
            data.put("content", bodyPart.getContent().toString());
            return data;
        }
        else if(Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) && bodyPart.getFileName() != null) {
            Map map = new HashMap();
            map.put("type", "attachment");
            map.put("fileName", bodyPart.getFileName());
            map.put("fileType", bodyPart.getContentType().substring(0, bodyPart.getContentType().indexOf(";")));
            map.put("mimeBodyPart", bodyPart);
            return map;
        }
        else if(bodyPart.getContentType().contains("multipart")) {
            Map o = processMultipart((Multipart) bodyPart.getContent());
            return o;
        }
        return null;
    }

    private static String toSingleLine(String str) throws Exception {
        return str.replaceAll("\\s+", " ");
    }

    private static void writeToFile(String location, String content) throws Exception {
        BufferedWriter out = new BufferedWriter(new FileWriter(location));
        out.write(content);
        out.close();
    }

    protected static void println(Object o) {
        System.out.println("" + o);
    }
}

Decode Util Class


package com.google_api;

/**
 * Created by pritom on 20/11/2016.
 */
public class Base64Decoder {
    private static final String ENCODING = "UTF-8";
    private static final byte[] CHUNK_SEPARATOR = new byte[]{(byte)13, (byte)10};
    private static final byte[] DECODE_TABLE = new byte[]{
            (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1,
            (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1,
            (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1,
            (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1,
            (byte)-1, (byte)-1, (byte)-1, (byte)62, (byte)-1, (byte)62, (byte)-1, (byte)63, (byte)52, (byte)53,
            (byte)54, (byte)55, (byte)56, (byte)57, (byte)58, (byte)59, (byte)60, (byte)61, (byte)-1, (byte)-1,
            (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)-1, (byte)0, (byte)1, (byte)2, (byte)3, (byte)4, (byte)5,
            (byte)6, (byte)7, (byte)8, (byte)9, (byte)10, (byte)11, (byte)12, (byte)13, (byte)14, (byte)15, (byte)16,
            (byte)17, (byte)18, (byte)19, (byte)20, (byte)21, (byte)22, (byte)23, (byte)24, (byte)25, (byte)-1,
            (byte)-1, (byte)-1, (byte)-1, (byte)63, (byte)-1, (byte)26, (byte)27, (byte)28, (byte)29, (byte)30,
            (byte)31, (byte)32, (byte)33, (byte)34, (byte)35, (byte)36, (byte)37, (byte)38, (byte)39, (byte)40,
            (byte)41, (byte)42, (byte)43, (byte)44, (byte)45, (byte)46, (byte)47, (byte)48, (byte)49, (byte)50, (byte)51};
    private final byte[] decodeTable;
    private final int decodeSize;
    private int bitWorkArea;
    private byte[] buffer;
    private int pos;
    private int readPos;
    private boolean eof;
    private int modulus;

    public static String decodeBase64(String raw) throws Exception {
        return new String(new Base64Decoder(0, CHUNK_SEPARATOR).decode(raw), ENCODING);
    }

    private Base64Decoder(int lineLength, byte[] lineSeparator) throws Exception {
        super();
        this.decodeTable = DECODE_TABLE;
        int encodeSize;
        if(lineSeparator != null) {
            if(this.containsAlphabetOrPad(lineSeparator)) {
                String sep = newStringUtf8(lineSeparator);
                throw new Exception("lineSeparator must not contain base64 characters: [" + sep + "]");
            }

            if(lineLength > 0) {
                encodeSize = 4 + lineSeparator.length;
                System.arraycopy(lineSeparator, 0, new byte[lineSeparator.length], 0, lineSeparator.length);
            } else {
                encodeSize = 4;
            }
        } else {
            encodeSize = 4;
        }

        this.decodeSize = encodeSize - 1;
    }

    private void decode(byte[] in, int inPos, int inAvail) {
        if(!this.eof) {
            if(inAvail < 0) {
                this.eof = true;
            }

            for(int i = 0; i < inAvail; ++i) {
                this.ensureBufferSize(this.decodeSize);
                byte b = in[inPos++];
                if(b == 61) {
                    this.eof = true;
                    break;
                }

                if(b >= 0 && b < DECODE_TABLE.length) {
                    byte result = DECODE_TABLE[b];
                    if(result >= 0) {
                        this.modulus = (this.modulus + 1) % 4;
                        this.bitWorkArea = (this.bitWorkArea << 6) + result;
                        if(this.modulus == 0) {
                            this.buffer[this.pos++] = (byte)(this.bitWorkArea >> 16 & 255);
                            this.buffer[this.pos++] = (byte)(this.bitWorkArea >> 8 & 255);
                            this.buffer[this.pos++] = (byte)(this.bitWorkArea & 255);
                        }
                    }
                }
            }

            if(this.eof && this.modulus != 0) {
                this.ensureBufferSize(this.decodeSize);
                switch(this.modulus) {
                    case 2:
                        this.bitWorkArea >>= 4;
                        this.buffer[this.pos++] = (byte)(this.bitWorkArea & 255);
                        break;
                    case 3:
                        this.bitWorkArea >>= 2;
                        this.buffer[this.pos++] = (byte)(this.bitWorkArea >> 8 & 255);
                        this.buffer[this.pos++] = (byte)(this.bitWorkArea & 255);
                }
            }

        }
    }

    private boolean isInAlphabet(byte octet) {
        return octet >= 0 && octet < this.decodeTable.length && this.decodeTable[octet] != -1;
    }

    private int available() {
        return this.buffer != null ? this.pos - this.readPos : 0;
    }

    private int getDefaultBufferSize() {
        return 8192;
    }

    private void resizeBuffer() {
        if(this.buffer == null) {
            this.buffer = new byte[this.getDefaultBufferSize()];
            this.pos = 0;
            this.readPos = 0;
        }
        else {
            byte[] b = new byte[this.buffer.length * 2];
            System.arraycopy(this.buffer, 0, b, 0, this.buffer.length);
            this.buffer = b;
        }
    }

    private void ensureBufferSize(int size) {
        if(this.buffer == null || this.buffer.length < this.pos + size) {
            this.resizeBuffer();
        }

    }

    private int readResults(byte[] b, int bPos, int bAvail) {
        if(this.buffer != null) {
            int len = Math.min(this.available(), bAvail);
            System.arraycopy(this.buffer, this.readPos, b, bPos, len);
            this.readPos += len;
            if(this.readPos >= this.pos) {
                this.buffer = null;
            }
            return len;
        }
        else {
            return this.eof ? -1 : 0;
        }
    }

    private void reset() {
        this.buffer = null;
        this.pos = 0;
        this.readPos = 0;
        this.modulus = 0;
        this.eof = false;
    }

    private byte[] decode(String pArray) throws Exception {
        return this.decode(getBytesUtf8(pArray));
    }

    private byte[] decode(byte[] pArray) {
        this.reset();
        if(pArray != null && pArray.length != 0) {
            this.decode(pArray, 0, pArray.length);
            this.decode(pArray, 0, -1);
            byte[] result = new byte[this.pos];
            this.readResults(result, 0, result.length);
            return result;
        } else {
            return pArray;
        }
    }

    private boolean containsAlphabetOrPad(byte[] arrayOctet) {
        if(arrayOctet == null) {
            return false;
        }
        else {
            for (byte element : arrayOctet) {
                if (61 == element || this.isInAlphabet(element)) {
                    return true;
                }
            }
            return false;
        }
    }

    private static byte[] getBytesUtf8(String string) throws Exception {
        return getBytesUnchecked(string, "UTF-8");
    }

    private static byte[] getBytesUnchecked(String string, String charsetName) throws Exception {
        return string.getBytes(charsetName);
    }

    private static String newString(byte[] bytes, String charsetName) throws Exception {
        return new String(bytes, charsetName);
    }

    private static String newStringUtf8(byte[] bytes) throws Exception {
        return newString(bytes, "UTF-8");
    }
}

Output would be as like if your user id and message id is correct:

Snippet=Hello bro how are you?Some italic mode text
Return-Path == xxx@gmail.com
From == xxx@gmail.com
Reply-To == "Reply To" <some_reply_address@gmails.com>
MIME-Version == 1.0
Date == Mon, 21 Nov 2016 00:31:53 -0500
Subject == Test email on: 21/11/2016 06:31:44
To == "To Address" <xxx@xxx.com>
Content-Type == multipart/mixed; boundary="5258f110dfc605186344f1668864cea5"
Message-Id == <CAD-od7dd=JedEjLxQPLLTMwJ93ZSpWdwZHsWD_eL-Jr1M=iWWA@mail.gmail.com>
Key=<<attachments>> == [
	{fileName=My-pdf.pdf, mimeBodyPart=javax.mail.internet.MimeBodyPart@490ab905, type=attachment, fileType=application/pdf}, 
	{fileName=My-image.png, mimeBodyPart=javax.mail.internet.MimeBodyPart@56ac3a89, type=attachment, fileType=image/png}
]
Key=<<html>> == <b>Hello bro how are you?</b><i style='color:blue;'>Some italic mode text</i>
Key=<<text>> == 

Php send email using google oauth

You can get access token & other details to perform this action:
http://pritomkumar.blogspot.com/2016/11/using-oauth-20-for-google-client-side.html

Code snippet to send mail using google & php using google oauth


<?php
session_start();
init();

if(isset($_POST["send"])) {
    sendEmail();
}
else {
?>
<form method="post" enctype="multipart/form-data" accept-charset="ISO-8859-1">
    <table style="width: 1000px;">
        <tr>
            <td style="width: 150px;">To</td>
            <td style="width: 850px;"><input type="text" name="to" required value="" style="width: 100%;"/></td>
        </tr>
        <tr>
            <td>Subject</td>
            <td><input type="text" name="subject" required value="Some sample subject on <?php echo date("d/m/Y H:i:s"); ?>" style="width: 100%;"/></td>
        </tr>
        <tr>
            <td>Files</td>
            <td>
                <input type="file" name="files[]"/>
                <input type="file" name="files[]"/>
                <input type="file" name="files[]"/>
                <input type="file" name="files[]"/>
                <input type="file" name="files[]"/>
                <input type="file" name="files[]"/>
            </td>
        </tr>
        <tr>
            <td style="vertical-align: top;">Message</td>
            <td><textarea name="message" required style="width: 100%; height: 600px;"></textarea></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" name="send" value="Send"/></td>
        </tr>
    </table>
</form>
<?php
}

function init() {
    $_SESSION["google_user_id"] = "118224585666607576118";
    $_SESSION["access_token"] = "ya29.CjCgdfgdfgdfgROwgDCiVa4ZvfzThKO6I272GJGQoWIEmwvgcNtks0exmxlUmzQ";

    /* Permissions need to send email */
    $_SESSION["scope"] = "https://www.googleapis.com/auth/userinfo.profile"; /* User profile */
    $_SESSION["scope"] .= " https://www.googleapis.com/auth/gmail.send"; /* Send email */
}

function sendEmail() {
    $to = trim($_POST["to"]);
    if (strlen($to) == 0) {
        die("Need email address to send email");
    }

    $cc = "";
    $bcc = "";
    $nl = "\r\n";
    $boundary = md5(date('r', time()));

    $html = trim(utf8_encode($_POST["message"]));

    $attachment_body = "";
    for($i = 0; $i < 6; $i++) {
        if(strlen(trim($_FILES["files"]["name"][$i])) > 0) {
            $content = file_get_contents($_FILES["files"]["tmp_name"][$i]);
            $content = base64_encode($content);
            $this_attachment = "--".$boundary.$nl."Content-Type: ".$_FILES["files"]["type"][$i].$nl;
            $this_attachment .= "Content-Transfer-Encoding: base64$nl";
            $this_attachment .= "Content-Disposition: attachment; filename=\"".$_FILES["files"]["name"][$i]."\"$nl$nl";
            $this_attachment .= $content;

            $attachment_body .= $this_attachment.$nl;
        }
    }

    $message = "Return-Path: pritomkucse@gmail.com$nl".
        "From: your_email@gmail.com$nl".
        "Reply-To: \"Reply To\" <some_reply_address@gmails.com>$nl".
        "MIME-Version: 1.0$nl".
        "Date: ".date('d/m/Y H:i:s')."$nl".
        "Subject: Test email on: ".date("d/m/Y H:i:s")."$nl".
        "To: $to$nl".
        //"CC: \"CC Address\" <$cc>$nl".
        //"BCC: \"BCC Address\" <$bcc>$nl".
        "Content-Type: multipart/mixed; boundary=\"$boundary\"$nl$nl".
        "--$boundary$nl".
        "Content-Type: text/html; charset=iso-8859-1".$nl.
        "Content-Transfer-Encoding: 7bit$nl$nl".
        "$html$nl".
        "$attachment_body".
        "--$boundary--";

    echo "<pre>[[";print_r($message);echo "]]</pre>";

    $submit = array();
    $submit["raw"] = encode_content($message);
    $submit = json_encode($submit);

    $headers = array();
    $headers[] = "Content-Type: application/json";
    $headers[] = "Content-Length: " . strlen($submit);

    $apiUrl = "https://www.googleapis.com/gmail/v1/users/";
    $apiUrl .= $_SESSION["google_user_id"]."/messages/send?format=raw";
    $apiUrl .= "&access_token=".$_SESSION["access_token"];

    $result = runCurl($apiUrl, $submit, $headers);
    echo "<pre>"; echo $result; echo "</pre>"; die();
    /*
    $result will print output as below:
    You can get unique Message-ID by read an email from server
    with email id "1588519a5db4ecfe" (as below)

    HTTP/1.1 200 OK
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Pragma: no-cache
    Expires: Mon, 01 Jan 1990 00:00:00 GMT
    Date: Mon, 21 Nov 2016 04:16:40 GMT
    Vary: X-Origin
    Content-Type: application/json; charset=UTF-8
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    X-XSS-Protection: 1; mode=block
    Server: GSE
    Alt-Svc: quic=":443"; ma=2592000; v="36,35,34"
    Accept-Ranges: none
    Vary: Origin,Accept-Encoding
    Transfer-Encoding: chunked

    {
        "id": "1588519a5db4ecfe",
        "threadId": "1588519a5db4ecfe",
        "labelIds": [
            "SENT"
        ]
    }
    */
}

function encode_content($content) {
    $content = base64_encode($content);
    $content = str_replace("+", "-", $content);
    $content = str_replace("/", "_", $content);
    //$content = rawurlencode($content);
    return $content;
}

function runCurl($url, $post = null, $headers = null) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, $post == null ? 0 : 1);
    if($post != null) {
        curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
    }
    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSLVERSION, 1);
    if($headers != null) {
        curl_setopt($curl, CURLOPT_HEADER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    }
    $response = curl_exec($curl);
    $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    curl_close($curl);
    if($http_code >= 400) {
        echo "Error executing request to Office365 api with error code=$http_code<br/><br/>\n\n";
        echo "<pre>"; print_r($response); echo "</pre>";
        die();
    }
    return $response;
}
?>

Php parse email body & attachments received from google account by oauth2

Email received from google account using oauth2:


stdClass Object
(
    [id] => 15885340ba6b9ba9
    [threadId] => 15885344ba2b9ba9
    [labelIds] => Array
        (
            [0] => SENT
        )

    [snippet] => Hello bro how are you?Some italic mode text
    [historyId] => 685672
    [internalDate] => 1479703529000
    [payload] => stdClass Object
        (
            [mimeType] => multipart/mixed
            [filename] => 
            [headers] => Array
                (
                    [0] => stdClass Object
                        (
                            [name] => Received
                            [value] => from 48568800665 named unknown by gmailapi.google.com with HTTPREST; Sun, 20 Nov 2016 23:45:29 -0500
                        )

                    [1] => stdClass Object
                        (
                            [name] => Return-Path
                            [value] => pritomkucse@xxx.com
                        )

                    [2] => stdClass Object
                        (
                            [name] => From
                            [value] => xxx.xxx@xxx.com
                        )

                    [3] => stdClass Object
                        (
                            [name] => Reply-To
                            [value] => Reply To <some_reply_address@gmails.com>
                        )

                    [4] => stdClass Object
                        (
                            [name] => MIME-Version
                            [value] => 1.0
                        )

                    [5] => stdClass Object
                        (
                            [name] => Date
                            [value] => Sun, 20 Nov 2016 23:45:29 -0500
                        )

                    [6] => stdClass Object
                        (
                            [name] => Subject
                            [value] => Test email on: 21/11/2016 05:45:23
                        )

                    [7] => stdClass Object
                        (
                            [name] => To
                            [value] => To Address <some_to_address@xxx.com>
                        )

                    [8] => stdClass Object
                        (
                            [name] => CC
                            [value] => CC Address <some_cc_address@xxx.com>
                        )

                    [9] => stdClass Object
                        (
                            [name] => Content-Type
                            [value] => multipart/mixed; boundary="4abf1fca8718965424d6569f69ecf783"
                        )

                    [10] => stdClass Object
                        (
                            [name] => Message-Id
                            [value] => <CAD-od7e+ZAOzrQLU-b4O5ZrLP0x0qEkaYnwNB4gBj60bSbd8DQ@mail.gmail.com>
                        )

                )

            [body] => stdClass Object
                (
                    [size] => 0
                )

            [parts] => Array
                (
                    [0] => stdClass Object
                        (
                            [partId] => 0
                            [mimeType] => text/html
                            [filename] => 
                            [headers] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [name] => Content-Type
                                            [value] => text/html; charset=UTF-8
                                        )

                                    [1] => stdClass Object
                                        (
                                            [name] => Content-Transfer-Encoding
                                            [value] => 7bit
                                        )

                                )

                            [body] => stdClass Object
                                (
                                    [size] => 77
                                    [data] => PGI-SGVsbG8gYnJv.....
                                )

                        )

                    [1] => stdClass Object
                        (
                            [partId] => 1
                            [mimeType] => application/pdf
                            [filename] => My-pdf.pdf
                            [headers] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [name] => Content-Type
                                            [value] => application/pdf; name="My-pdf.pdf"
                                        )

                                    [1] => stdClass Object
                                        (
                                            [name] => Content-Transfer-Encoding
                                            [value] => base64
                                        )

                                    [2] => stdClass Object
                                        (
                                            [name] => Content-Disposition
                                            [value] => attachment; filename="My-pdf.pdf"
                                        )

                                )

                            [body] => stdClass Object
                                (
                                    [attachmentId] => ANGjdJ_iTdTRG38Nwxf8...
                                    [size] => 197132
                                )

                        )

                    [2] => stdClass Object
                        (
                            [partId] => 2
                            [mimeType] => image/png
                            [filename] => My-image.png
                            [headers] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [name] => Content-Type
                                            [value] => image/png; name="My-image.png"
                                        )

                                    [1] => stdClass Object
                                        (
                                            [name] => Content-Transfer-Encoding
                                            [value] => base64
                                        )

                                    [2] => stdClass Object
                                        (
                                            [name] => Content-Disposition
                                            [value] => attachment; filename="My-image.png"
                                        )

                                )

                            [body] => stdClass Object
                                (
                                    [attachmentId] => ANGjdJ9AysXkrs_yEFM0...
                                    [size] => 317154
                                )

                        )

                )

        )

    [sizeEstimate] => 686890
)

Php code to parse email body & attachments:


<?php
function viewEmailById() {
    $id = $_GET["email_by_id"];
    $raw = "";// "format=raw&";
    $fields = "";// "fields=raw&";
    $apiUrl = "https://www.googleapis.com/gmail/v1/users/";
    $apiUrl .= getUserID()."/messages/$id?$raw$fields";
    $apiUrl .= "access_token=".token();
    $result = json_decode(runCurl($apiUrl));

    $message = parseEmail($result->payload->parts);
    if(!file_exists($id)) {
        mkdir($id);
    }
    $link = "";
    foreach($message as $msg) {
        $location = $id."/".$msg["name"];
        $fp = fopen("$location","w");
        fwrite($fp, $msg["body"]);
        fclose($fp);
        $link .= "<a href='".$location."' target='_blank'>".$msg["name"]."</a><br/>";
    }
    echo $link;
}

function parseEmail($email) {
    $id = $_GET["email_by_id"];
    $result = array();
    for($i = 0; $i < count($email); $i++) {
        $part = $email[$i];
        $mime = $part->mimeType;
        $name = $part->filename;
        if(strlen($name) > 0) {
            $file = array();
            $file["type"] = $mime;
            $file["name"] = $name;
            $apiUrl = "https://www.googleapis.com/gmail/v1/users/".getUserID();
            $apiUrl .= "/messages/$id/attachments/".$part->body->attachmentId;
            $apiUrl .= "?access_token=".token();
            $remoteFile = json_decode(runCurl($apiUrl));
            $file["body"] = decodeContent($remoteFile->data);
            array_push($result, $file);
        }
        else if($mime === "text/plain") {
            $file = array();
            $file["type"] = "text";
            $file["name"] = "email_body_plain.html";
            $file["body"] = decodeContent($part->body->data);
            array_push($result, $file);
        }
        else if($mime === "text/html") {
            $file = array();
            $file["type"] = "html";
            $file["name"] = "email_body_html.html";
            $file["body"] = decodeContent($part->body->data);
            array_push($result, $file);
        }
        else if(substr($mime, 0, 9) === "multipart") {
            foreach(parseEmail($part->parts) as $file) {
                array_push($result, $file);
            }
        }
    }
    return $result;
}

function decodeContent($content) {
    return base64_decode(str_replace("-", "+", str_replace("_", "/", $content)));
}

function getUserID() {
    $fromSession = valueFromSession("user_id");
    if($fromSession) {
        return $fromSession;
    }
    else {
        $apiUrl = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json";
        $apiUrl .= "&access_token=".token();
        $result = json_decode(runCurl($apiUrl));
        $_SESSION["user_id"] = $result->id;
        return $_SESSION["user_id"];
    }
}

function valueFromSession($name) {
    if(isset($_SESSION[$name])) {
        return $_SESSION[$name];
    }
    return null;
}

function token() {
    return "return your access token from here";
}

function runCurl($url, $post = null, $headers = null) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, $post == null ? 0 : 1);
    if($post != null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    }
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    if($headers != null) {
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    $result = curl_exec($ch);
    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    $test = json_decode($result);
    if((isset($test->error) && $test->error->code == 401) || $httpcode == 401) {
        if(!valueFromSession("redirected")) {
            $_SESSION["redirected"] = true;
            refreshToken();
            header("Refresh:0");
            die();
        }
        else {
            $_SESSION["redirected"] = null;
            echo "Error getting data from google api, reload page to try again";
            die();
        }
    }
    else {
        $_SESSION["redirected"] = null;
    }
    return $result;
}
?>

Thursday, November 17, 2016

Stylish CSS3 Loader

Example


Html Content

<div class="load-more-option"></div>

CSS Content

<style type="text/css">
    .load-more-option, .load-more-option:before, .load-more-option:after {
        border-radius: 50%;
        width: 2.5em;
        height: 2.5em;
        -webkit-animation-fill-mode: both;
        animation-fill-mode: both;
        -webkit-animation: load_more_options 1.8s infinite ease-in-out;
        animation: load_more_options 1.8s infinite ease-in-out;
    }
    .load-more-option {
        color: #37829e;
        font-size: 10px;
        margin: 80px auto;
        position: relative;
        text-indent: -9999em;
        -webkit-transform: translateZ(0);
        -ms-transform: translateZ(0);
        transform: translateZ(0);
        -webkit-animation-delay: -0.16s;
        animation-delay: -0.16s;
    }
    .load-more-option:before, .load-more-option:after {
        content: '';
        position: absolute;
        top: 0;
    }
    .load-more-option:before {
        left: -3.5em;
        -webkit-animation-delay: -0.32s;
        animation-delay: -0.32s;
    }
    .load-more-option:after {
        left: 3.5em;
    }
    @-webkit-keyframes load_more_options {
        0%,
        80%,
        100% {
            box-shadow: 0 2.5em 0 -1.3em;
        }
        40% {
            box-shadow: 0 2.5em 0 0;
        }
    }
    @keyframes load_more_options {
        0%,
        80%,
        100% {
            box-shadow: 0 2.5em 0 -1.3em;
        }
        40% {
            box-shadow: 0 2.5em 0 0;
        }
    }
</style>


Another Example Given Below



Example



HTML Content

<div class="loader"></div>
<div class="loader2"></div>

CSS Content

.loader {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  border: 4px solid lightgray;
  border-top: 4px solid #3498db;
  border-bottom: 4px solid #3498db;
  animation: spinxxx 2s linear infinite;
  -webkit-animation: spinxxx 2s linear infinite;
}
.loader2{
  width: 80px;
  height: 80px;
  margin: 16px;
  margin-top: -107px;
  margin-left: 20px;
  border-radius: 50%;
  border: 4px solid lightgray;
  border-top: 4px solid #3498db;
  animation: spinxxx2 2s linear infinite;
  -webkit-animation: spinxxx2 2s linear infinite;
}

@-webkit-keyframes spinxxx {
  0% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(360deg); }
}

@keyframes spinxxx {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@-webkit-keyframes spinxxx2 {
  0% { -webkit-transform: rotate(360deg); }
  100% { -webkit-transform: rotate(0deg); }
}

@keyframes spinxxx2 {
  0% { transform: rotate(360deg); }
  100% { transform: rotate(0deg); }
}




Wednesday, November 16, 2016

Angular-js infinity scroll to load more data on window or other element scrolling


<!DOCTYPE html>
<html>
    <head>
        <title>Infinite scrolling to load more data using angular-js</title>
        <style type="text/css">
            div.scroll-test {
                height: 100%;
                background: #123213;
                color: #fff;
                overflow: auto;
                margin: 0 auto;
                padding: 0.5em;
            }
        </style>
        
        <script src="http://code.angularjs.org/1.2.12/angular.js"></script>
        <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
        
        <script type="text/javascript">
            var app = angular.module("myApp", []);
           
            app.controller("ScrollController", function($scope, $http) {
                $scope.items = ["You have to scroll down to load more items..."];
                $scope.loading = false;
                $scope.counter = 0;
                $scope.rows = 1;
                
                var s = "----------------------------------------------------";
                s += "-------------------------------------------------------";
                s += "-------------------------------------------------------";
                
                $scope.loadMore = function() {
                    if(!$scope.loading) {
                        $scope.loading = true;
                        $http({
                            method: "GET",
                            url: "http://localhost/scroll/data.html?counter=" + ($scope.counter++)
                        }).success(function(data, status, header, config) {
                            $scope.loading = false;
                            data = data.split("\n");
                            for(i = 0; i < data.length - 1; i++) {
                                $scope.items.push(($scope.rows++) + "=" + data[i]);
                            }
                            $scope.items.push(($scope.rows++) + s);
                        });
                    }
                };
                
                var params = {};
                window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(str, key, value) {
                    params[key] = decodeURIComponent(value.replace(/\+/g, ' '));
                });
                var type = params.type === undefined ? '' : params.type;
                
                $scope.window = true;
                if(type == 'window') {
                    //Initializing the list
                    $scope.loadMore();
                }
                else if(type == 'div') {
                    $scope.window = false;
                    $("div.scroll-test").height(window.innerHeight - 130);
                    //Initializing the list
                    $scope.loadMore();
                }
                else {
                    $scope.items.push("You have to define 'type' parameter in url & value would be 'window' or 'div' as ?type=window");
                }
            });
            
            app.directive("windowScroll", function ($window) {
                return function(scope, element, attrs) {
                    angular.element($window).bind("scroll", function() {
                        if(scope.window && $window.pageYOffset + $(window).height() + 50 >= $(document).height()) {
                            scope.$apply(attrs.windowScroll);
                        }
                    });
                };
            });
           
            app.directive("divScroll", function() {
                return {    
                    restrict: 'A',
                    link: function(scope, element, attrs) {
                        var raw = element[0];
                        element.bind("scroll", function() {
                            if(!scope.window && raw.scrollTop + raw.offsetHeight + 50 >= raw.scrollHeight) {
                                scope.$apply(attrs.divScroll);
                            }
                        });
                    }
                }
            });
        </script>
    </head>

    <body>
         <div data-ng-app="myApp" data-window-scroll="loadMore()" data-ng-controller="ScrollController">
             <div>
                 <div class="scroll-test" data-div-scroll="loadMore()">
                     <p data-ng-repeat="item in items">
                         {{item}}
                     </p>
                 </div>
                <h1><i>INFINITE SCROLLING IN ANGULAR-JS<span data-ng-show="loading"> (Loading items...)</span></i></h1>              
             </div>       
         </div>
    </body>
</html>

jQuery get params from url

var params = {};
window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(str, key, value) {
    params[key] = decodeURIComponent(value.replace(/\+/g, ' '));
});
console.log(params);

Tuesday, November 15, 2016

GIT: Updates were rejected because a pushed branch tip is behind its remote

git push -f

The -f makes this a "forced push" and overwrites the branch on the working branch on the server. That would be gone wrong when you are working with other team members. But you can force push when you sure that your local state is correct then it should be fine. You risk losing commit history if that is not the case.