Monday, November 7, 2016

Grails send email using grails.plugin.mail.MailService and track unique message ID

At first have to extend "grails.plugin.mail.MailService" as follows:

class MyMailService extends MailService

MyMailService would be like:

package com.pkm.services.mail

import grails.plugin.mail.MailMessageBuilder
import grails.plugin.mail.MailService
import org.springframework.mail.MailMessage
import org.springframework.mail.javamail.MimeMessageHelper

class MyMailService extends MailService {
    MailMessage sendMail(Closure callable) {
        if (isDisabled()) {
            throw new Exception("Sending emails disabled by configuration option")
            return null
        }

        MailMessageBuilder messageBuilder = mailMessageBuilderFactory.createBuilder(mailConfig)
        messageBuilder.multipart(true)

        /* Sending some custom headers with this email */
        Map<String, String> v = new HashMap<String,String>()
        v.put("header_1", "Header_1")
        v.put("header_2", "Header_2")
        messageBuilder.headers(v)

        callable.delegate = messageBuilder
        callable.resolveStrategy = Closure.DELEGATE_FIRST
        callable.call(messageBuilder)

        MailMessage mailMessage = messageBuilder.sendMessage(mailExecutorService)

        /* Reading unique message ID */
        MimeMessageHelper mimeMessageHelper = messageBuilder.getProperty("helper")
        String messageID = mimeMessageHelper.mimeMessage.getHeader("Message-ID").toString().trim()
        /* Now you can do your stuff with messageID */

        return mailMessage
    }
}
Use below code snippet to send mail
myMailService.sendMail() {
    mailSender.host = "host.mail.com"
    mailSender.javaMailProperties.put("mail.smtp.auth", "true")
    mailSender.username = "pritomkucse@gmail.com"
    mailSender.password = "xxxxxxxxx"
    mailSender.port = 569

    multipart true

    from "Pritom<pritomkucse@gmail.com>"
    to
    replyTo
    cc
    bcc
    subject
    text
    html
    attachBytes "some.name" "file_type" fileBytes
}
You need to add following dependency to BuildConfig.groovy as follows:
grails.project.dependency.resolution = {
    // inherit Grails' default dependencies
    inherits("global") {
        // specify dependency exclusions here; for example, uncomment this to disable ehcache:
        // excludes 'ehcache'
    }
    log "error" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
    checksums true // Whether to verify checksums on resolve
    legacyResolve false // whether to do a secondary resolve on plugin installation, not advised and here for backwards compatibility

    repositories {
        inherits true // Whether to inherit repository definitions from plugins

        grailsPlugins()
        grailsHome()
        mavenLocal()
        grailsCentral()
        mavenCentral()
        // uncomment these (or add new ones) to enable remote dependency resolution from public Maven repositories
        //mavenRepo "http://repository.codehaus.org"
        //mavenRepo "http://download.java.net/maven/2/"
        //mavenRepo "http://repository.jboss.com/maven2/"
    }

    dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes e.g.
        // runtime 'mysql:mysql-connector-java:5.1.29'
        // runtime 'org.postgresql:postgresql:9.3-1101-jdbc41'
        test "org.grails:grails-datastore-test-support:1.0.2-grails-2.4"
        compile "org.springframework:spring-orm:$springVersion"
        runtime 'mysql:mysql-connector-java:5.1.29'
    }

    plugins {
        // plugins for the build system only
        build ":tomcat:7.0.55"

        // plugins for the compile step
        compile ":scaffolding:2.1.2"
        compile ':cache:1.1.8'
        compile ":asset-pipeline:1.9.9"
        compile ":mail:1.0.5"

        // plugins needed at runtime but not for compilation
        runtime ":hibernate4:4.3.6.1" // or ":hibernate:3.6.10.18"
        runtime ":database-migration:1.4.0"
        runtime ":jquery:1.11.1"

        // Uncomment these to enable additional asset-pipeline capabilities
        //compile ":sass-asset-pipeline:1.9.0"
        //compile ":less-asset-pipeline:1.10.0"
        //compile ":coffee-asset-pipeline:1.8.0"
        //compile ":handlebars-asset-pipeline:1.3.0.3"
    }
}

Friday, November 4, 2016

Angularjs ajax get or post method example from controller


app.controller('TestController', function($scope, $http) {
    $scope.name = "Pritom Kumar";
    $scope.posts = ["a", "b"];
    
    $http.post('lists_json', {id: 1, name: $scope.name}).
    success(function(response, status, headers, config) {
        console.log("Success=" + response);
    }).
    error(function(response, status, headers, config) {
        console.log("Error=" + response);
    });
    
    $http.get('lists_json?id=1&name='+$scope.name+"&list="+$scope.posts).
    success(function(response, status, headers, config) {
        console.log("Success=" + response);
    }).
    error(function(response, status, headers, config) {
        console.log("Error=" + response);
    });
});

Thursday, November 3, 2016

How to install Laravel 5 with Xampp (Windows)

Requirements:
1. PHP 5.5.9 or above
2. OpenSSL PHP Extension
3. PDO PHP Extension
4. Mbstring PHP Extension
5. Tokenizer PHP Extension

First of all, we need Xampp, so we can download it from the official page

After you've downloaded and installed Xampp, we need to install Composer from official page

After install it, we can open a Windows terminal and write composer for execute the command:




We will configure a Virtual Host in Xampp for a Laravel project, and in this example, we want to configure the domain laravel.local for our project.
We need to edit httpd-vhosts.conf that is located in C:\xampp\apache\conf\extra\httpd-vhosts.conf and add following lines at the end of the file:


<VirtualHost laravel.local:80>
    DocumentRoot "C:\xampp\htdocs\laravel\public"
    ServerAdmin laravel.local
    <Directory "C:\xampp\htdocs\laravel">
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Now we have to configure our hosts file that allows to redirect laravel.local to the localhost that is located in C:\Windows\System32\drivers\etc, add "127.0.0.1 laravel.local" to the  end of the file named "hosts".

We are prepared to install and configure a Laravel Framework. First of all, we have to navigate to "C:\xampp\htdocs" folder to install it and run this following command:


composer create-project laravel/laravel your_folder







Finally, have to start our Apache and MySql from Xampp control panel



And need to start laravel as server using following command:

php artisan serve --port=45

and navigate to http://localhost:45 from browser:


Create new controller & view in laravel

Open command prompt & navigate to "C:/xampp/htdocs/laravel" (laravel is your laravel project directory) and run following command:

php artisan make:controller TestController

This command will make a controller under directory "app/Http/Controllers"

Now add the following lines to "app/Http/routes.php":
Route::resource('test', 'TestController');

Now create a file named "test.blade.php" under "resources/views" directory with following contents:
Resources/views/test.blade.php<br/>
Name found from params=<?php echo $name; ?>

Your Controller class look like following:


<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use View;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class TestController extends Controller
{
    public function index()
    {
        $data = array();
        $data["name"] = "Pritom Kumar";
        return View::make('test', $data);
    }

    public function create()
    {
        
    }

    public function store(Request $request)
    {
        
    }

    public function show($id)
    {
        
    }

    public function edit($id)
    {
        
    }

    public function update(Request $request, $id)
    {
        
    }

    public function destroy($id)
    {
        
    }
}

?>

Now you can view output by browsing following url: {LARAVEL_ROOT_URL}"/test" 

Not receiving Google OAuth refresh token

The refresh_token is only provided on the first authorization from the user. Subsequent authorizations, such as the kind you make while testing an OAuth2 integration, will not return the refresh_token again.

Go to your account security settings: 
https://security.google.com/settings/security/permissions?pli=1.

Then click "Revoke Access" next to your app.
The next OAuth2 request you make will return a refresh_token.

You need "access_type=offline" & "approval_prompt=force" in all cases when you want the refresh_token.

List of google apps connected to my google account:

Using OAuth 2.0 for Google Client-side Web Applications


http://pritomkumar.blogspot.com/2016/11/php-send-email-using-google-oauth2.html
1. Obtain OAuth 2.0 credentials from the Google API Console.
First visit to https://console.developers.google.com/ and follow the steps:
Click the "Credentials" as below image:


Now click on "Create credentials" right most part of button and then you can see a dropdown menu as below image:


Now click on "OAuth client ID"
It will show a page like and select "Web application" as below image and provide "Name" and "Authorized redirect URIs" as described and click "Create":



NB: it can say you to create a project, then create a project by click the button.

It will take you to the OAuth client page where you can see "Client ID" & "Client Secret" which would be need later.




You can enable any of your service from google account from list below for specific project:




All google products listed here:
https://developers.google.com/products/

2. Now its time to connect to google via OAuth (Its PHP code snippet):
You have to define your scope first:
$scope = "https://www.googleapis.com/auth/userinfo.profile%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/gmail.readonly";
$auth_url = "https://accounts.google.com/o/oauth2/v2/auth";
$client_id = "YOUR CLIENT ID FROM GOOGLE";
$redirect_uri = "http://localhost/tappi/";

$forward_url = $auth_url."?scope=".$scope."&redirect_uri=".urlencode($redirect_uri)."&response_type=code&client_id=".urlencode($client_id);
header("Location: ".$url);

It will redirect you to the following page (if not logged in, login then):




Now click "Allow" button direct you to url you provided when creating application with a code in get parameter
Now you can get access token using the code received.
Full example code below:


<?php
session_start();
init();

if(token() != null) {
    echo "<a href='".$_SESSION["redirect_uri"]."'>Home</a>";
    echo " || <a href='".$_SESSION["redirect_uri"]."?refresh_token=true'>Refresh token</a>";
    echo " || <a href='".$_SESSION["redirect_uri"]."?profile=true'>Profile</a>";
    echo " || <a href='".$_SESSION["redirect_uri"]."?logout=true'>Logout</a><br/><br/>\n\n";
}

if(isset($_GET["logout"])) {
    flushToken();
    echo "Logged out<br/>";
    echo "<a href='".$_SESSION["redirect_uri"]."'>Start new session</a>";
    die();
}
else if(isset($_GET["refresh_token"])) {
    refreshToken();
    header("Location: ".$_SESSION["redirect_uri"]);
}
else if(isset($_GET["profile"])) {
    viewProfile();
}
else if(token() != null) {
    echo "<pre>";print_r(token());echo "</pre>";
}
else if(isset($_GET["code"])) {
    $post = "code=".urlencode($_GET["code"])."&client_id=".urlencode($_SESSION["client_id"]);
    $post .= "&client_secret=".urlencode($_SESSION["client_secret"]);
    $post .="&redirect_uri=".urlencode($_SESSION["redirect_uri"]);
    $post .= "&grant_type=authorization_code";
    $result = json_decode(runCurl($_SESSION["token_url"], $post));
    storeToken($result);
    if(isset($result->refresh_token)) {
        file_put_contents("rt-".getUserID().".txt", $result->refresh_token);
    }
    file_put_contents("active.txt", getUserID());
    file_put_contents("access_token.txt", $result->access_token);
    header("Location: " . $_SESSION["redirect_uri"]);
}
else {
    $url = $_SESSION["auth_url"]."?scope=".urlencode($_SESSION["scope"]).
        "&redirect_uri=".urlencode($_SESSION["redirect_uri"]).
        "&response_type=code&client_id=".urlencode($_SESSION["client_id"])."&access_type=offline";
    echo "<a href='".$url."'>Authorize with Google</a>";
}

function refreshToken() {
    $post = "client_id=".urlencode($_SESSION["client_id"]);
    $post .= "&client_secret=".urlencode($_SESSION["client_secret"]);
    $post .= "&redirect_uri=".urlencode($_SESSION["redirect_uri"]);
    $post .= "&grant_type=refresh_token&refresh_token=".urlencode(getRefreshToken());
    $result = json_decode(runCurl($_SESSION["token_url"], $post));
    file_put_contents("access_token.txt", $result->access_token);
    storeToken($result);
}

function getRefreshToken() {
    $active = file_get_contents("active.txt");
    return file_get_contents("rt-".$active.".txt");
}

function flushToken() {
    file_put_contents("auth.txt", "");
    $_SESSION["redirected"] = null;
}

function token() {
    $text = file_exists("auth.txt") ? file_get_contents("auth.txt") : null;
    if($text != null && strlen($text) > 0) {
        return json_decode($text);
    }
    return null;
}

function storeToken($o) {
    file_put_contents("auth.txt", json_encode($o));
}

function init() {
    $_SESSION["auth_url"] = "https://accounts.google.com/o/oauth2/v2/auth";
    $_SESSION["token_url"] = "https://accounts.google.com/o/oauth2/token";
    $_SESSION["client_id"] = "892386593019-xxxxxxxxxinht701m7kn0gkoj964r2.apps.googleusercontent.com";
    $_SESSION["client_secret"] = "bVQ_xT0ZxxxxxxxxxxvV9zRV3";
    $_SESSION["redirect_uri"] = "http://localhost/tappi/google.php";
    $_SESSION["scope"] = "https://www.googleapis.com/auth/userinfo.profile"; /* User profile */
    $_SESSION["scope"] .= " https://www.googleapis.com/auth/userinfo.email"; /* User email address */
    $_SESSION["scope"] .= " https://www.googleapis.com/auth/gmail.readonly"; /* Read mail */
    $_SESSION["scope"] .= " https://www.googleapis.com/auth/gmail.send"; /* Send email */
}

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

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

function viewProfile() {
    $apiUrl = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json";
    $apiUrl .= "&access_token=".token()->access_token;
    $result = json_decode(runCurl($apiUrl));
    echo "<pre>";
    print_r($result);
    echo "</pre>";
}

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;
}
?>