Showing posts with label gmail. Show all posts
Showing posts with label gmail. Show all posts

Saturday, September 15, 2018

GCP Authentication: RefreshError

Leave a Comment

In order to round-trip test mail sending code in our GCP backend I am sending an email to a GMail inbox and attempting to verify its arrival. The current mechanism for authentication to the GMail API is fairly standard, pasted from the GMail API documentation and embedded in a function:

def authenticate():     """Authenticates to the Gmail API using data in credentials.json,     returning the service instance for use in queries etc."""     store = file.Storage('token.json')     creds = store.get()     if not creds or creds.invalid:         flow = client.flow_from_clientsecrets(CRED_FILE_PATH, SCOPES)         creds = tools.run_flow(flow, store)     service = build('gmail', 'v1', http=creds.authorize(Http()))     return service 

CRED_FILE_PATH points to a downloaded credentials file for the service. The absence of the token.json file triggers its re-creation after an authentication interaction via a browser window, as does the token's expiry.

This is an integration test that must run headless (i.e. with no interaction whatsoever). When re-authentication is required the test currently raises an exception when the authentication flow starts to access sys.argv, which means it sees the arguments to pytest!

I've been trying to find out how to authenticate reliably using a mechanism that does not require user interaction (such as an API key). Nothing in the documentation or on Stackoverflow seems to answer this question.

A more recent effort uses the keyfile from a service account with GMail delegation to avoid the interactive Oauth2 flows.

def authenticate():     """Authenticates to the Gmail API using data in g_suite_access.json,     returning the service instance for use in queries etc."""     main_cred = service_account.Credentials.from_service_account_file(         CRED_FILE_PATH, scopes=SCOPES)     # Establish limited credential to minimise any damage.     credentials = main_cred.with_subject(GMAIL_USER)     service = build('gmail', 'v1', credentials=credentials)     return service 

On trying to use this service with

        response = service.users().messages().list(userId='me',                                     q=f'subject:{subject}').execute() 

I get:

google.auth.exceptions.RefreshError:   ('unauthorized_client: Client is unauthorized to retrieve access tokens using this method.',    '{\n "error": "unauthorized_client",\n "error_description": "Client is unauthorized to retrieve access tokens using this method."\n}') 

I get the feeling there's something fundamental I'm not understanding.

1 Answers

Answers 1

The service account needs to be authorized or it cant access the emails for the domain.

"Client is unauthorized to retrieve access tokens using this method"

Means that you have not authorized it properly; check Delegating domain-wide authority to the service account

Source: Client is unauthorized to retrieve access tokens using this method Gmail API C#

Read More

Thursday, August 2, 2018

Email thumbnail URL changed to googleusercontent.com in gmail

Leave a Comment

I have a system whenever user upload an image, it will send an email to the registered user's gmail. But in the email, i see something like this, the thumbnail is not viewable.

enter image description here

I inspect on the element, and found the src linked to this url: https://blogger.googleusercontent.com/img/proxy/AVvXsEja73Yzvlrbp9zKoJ3xFpbT53laGl3Sryl9AEtDVT5fh8Oz9iPu88_T21Gaa7VxXllW55M_M022wEX8GbVZ5gyhHmm2nJML4ntalGpiv7jN8ve6dGjQqksdIzwiZt2nHunWZqyTFj2hyuJ0pSj2RZgS_qy-vGvGcQ7wJjS371Ug-Jj1J0o3M2RcHk1x2cGoutl1ShOphplAFPWkvWvrQnBshGOJWyvOC3w=s0-d-e1-ft

Obviously it is being cached by google proxy

But i can view the image without google user content, by accessing https://www.somedomain.com/files/1658/thumbnail_71JtDozxS1L._SY450_.jpg (i masked the domain so the image might not available to you).

I tried to clear browser cache but the problem still persist. How can i bypass the googleusercontent thingy or at least make the thumbnail able to display.

I checkout on this link Images not displayed for Gmail but im not using localhost and the image itself is accessible outside of my local network.

2 Answers

Answers 1

How does Google Image Proxy work

The Google Image Proxy is a caching proxy server. Every time an image link is included in email the request will go to the Google Image Proxy first to see if it has been cached, if so it should serve it up from the proxy or it will go fetch it and cache it there after.

The solution for most issues

The Google Image Proxy server will fetch your images if this images:

  • have extensions like .png, .jpg/.jpeg or .gif only. May be .webp too. But not .svg.
  • do not use any kind of query string part in the image URL like ?id=123
  • have an URL which is mapped onto the image directly.
  • have not a long name.

Requirements for image server:

  • The response from image server/proxy server must include the correct header like Content-Type: image/jpeg.
  • File extension and content-type header must be in the same type.
  • Status code in server response must be 200 instead of 403, 500 and etc.

What could help too?

Google support answer:

Set up an image URL proxy whitelist

When your users open email messages, Gmail uses Google’s secure proxy servers to serve images that might be included in these messages. This protects your users and domain against image-based security vulnerabilities.

Because of the image proxy, links to images that are dependent on internal IPs and sometimes cookies are broken. The Image URL proxy whitelist setting lets you avoid broken links to images by creating and maintaining a whitelist of internal URLs that'll bypass proxy protection.

When you configure the Image URL proxy whitelist, you can specify a set of domains and a path prefix that can be used to specify large groups of URLs. See the guidelines below for examples.

Configure the Image URL proxy whitelist setting:

  • Sign in to your Google Admin console. Sign in using your administrator account (does not end in @gmail.com).
  • From the Admin console Home page, go to Apps > G Suite > Gmail > Advanced settings. Tip: To see Advanced settings, scroll to the bottom of the Gmail page.
  • On the left, select your top-level organization.
  • Scroll to the Image URL proxy whitelist section.
  • Enter image URL proxy whitelist patterns. Matching URLs will bypass image proxy protection. See the guidelines below for more details and instructions.
  • At the bottom, click Save.

It can take up to an hour for changes to propagate to user accounts. You can track prior changes under Admin console audit log.

Guidelines for applying the Image URL proxy whitelist setting

Security considerations

Consult with your security team before configuring the Image URL proxy whitelist setting. The decision to bypass image proxy whitelist protection can expose your users and domain to security risks if not used with care.

In general, if you have a domain that needs authentication via cookie, and if that domain is controlled by an administrator within your organization and is completely trusted, then whitelisting that URL should not expose your domain to image-based attacks.

Important: Disabling the image proxy is not recommended. This option is available to provide flexibility for administrators, but disabling the image proxy can leave your users vulnerable to malicious attacks.

Entering Image URL patterns

To maintain a whitelist of internal URLs that'll bypass proxy protection, enter the image URL patterns in the Image URL proxy whitelist setting. Matching URLs will bypass the image proxy.

A pattern can contain the scheme, the domain, and a path. The pattern must always have a forward slash (/) present between the domain and path. If the URL pattern specifies a scheme, then the scheme and the domain must fully match. Otherwise, the domain can partially match the URL suffix. For example, the pattern google.com matches www.google.com, but not gle.com. The URL pattern can specify a path that's matched against the path prefix.

Important: Enter your actual domain name as you enter the image URL pattern. Always include a trailing forward slash (/) after the domain name.

Examples of Image URL patterns

The following patterns are examples only. The following patterns:

http://rule_fixed_scheme_domain.com/ rule_flex_scheme_domain.com/ rule_fixed_subpath.com/cgi-bin/ 

... will match the following URLs:

http://rule_fixed_scheme_domain.com/ http://rule_fixed_scheme_domain.com/test.jpg?foo=bar#frag http://rule_fixed_scheme_domain.com rule_flex_scheme_domain.com/ t.rule_flex_scheme_domain.com/test.jpg http://t.rule_flex_scheme_domain.com/test.jpg https://t.rule_flex_scheme_domain.com/test.jpg http://rule_fixed_subpath.com/cgi-bin/ http://rule_fixed_subpath.com/cgi-bin/people 

Note: The URL scheme (http://) is optional. If the scheme is omitted, the pattern can match any scheme, and allows partial matches on the domain suffix.

Previewing the image URL patterns

Click Preview to see if the URLs match the image URL patterns you've set. If the image URL matches a pattern, you'll see a confirmation message. If the image URL does not match, an error message appears.

Answers 2

How can i bypass the googleusercontent thingy or at least make the thumbnail able to display

Just put your images as base64 instead of URLs. Or try to shorten the name of image, one of this steps definitely should has effect.

Read More

Monday, July 30, 2018

Laravel mail with g suites and XOAUTH2

Leave a Comment

I have a g suites account and applications associated with my e-mails. I was looking at the Laravel mail functions but I do not see any option to log in to gmail smtp with xoauth auth type.

I was using PHPMailer with codeigniter and I had to use clientId, clientSecret and refreshToken to send emails via smtp.gmail.com

Is there any chance I can authenticate using xoauth with native laravel swiftmailer?

1 Answers

Answers 1

Since Laravel doesn't have available configuration to set AuthMode then we need to tweak it a little bit.

  1. Register a new Mail service provider in config/app.php:

    // ... 'providers' => [     // ...      // Illuminate\Mail\MailServiceProvider::class,     App\MyMailer\MyMailServiceProvider::class,      // ... 
  2. app/MyMailer/MyMailServiceProvider.php should create your own TransportManager class:

```

namespace App\MyMailer;  class MyMailServiceProvider extends \Illuminate\Mail\MailServiceProvider {     public function registerSwiftTransport()     {         $this->app['swift.transport'] = $this->app->share(function ($app) {              return new MyTransportManager($app);         });     } } 

```

  1. In the app/MyMailer/MyTransportManager.php we can provide additional configuration to the SwiftMailer:

```

<?php  namespace App\MyMailer;   class MyTransportManager extends \Illuminate\Mail\TransportManager {     /**      * Create an instance of the SMTP Swift Transport driver.      *      * @return \Swift_SmtpTransport      */     protected function createSmtpDriver()     {         $transport = parent::createSmtpDriver();         $config = $this->app->make('config')->get('mail');           if (isset($config['authmode'])) {             $transport->setAuthMode($config['authmode']);         }          return $transport;     } } 

```

  1. Last thing to do is to provide mail configuration with authmode set to XOAUTH2 and password to your access token:

```

<?php  return array(  /* |-------------------------------------------------------------------------- | Mail Driver |-------------------------------------------------------------------------- | | Laravel supports both SMTP and PHP's "mail" function as drivers for the | sending of e-mail. You may specify which one you're using throughout | your application here. By default, Laravel is setup for SMTP mail. | | Supported: "smtp", "mail", "sendmail" | */  'driver' => 'smtp',  /* |-------------------------------------------------------------------------- | SMTP Host Address |-------------------------------------------------------------------------- | | Here you may provide the host address of the SMTP server used by your | applications. A default option is provided that is compatible with | the Postmark mail service, which will provide reliable delivery. | */  'host' => 'smtp.gmail.com',  /* |-------------------------------------------------------------------------- | SMTP Host Port |-------------------------------------------------------------------------- | | This is the SMTP port used by your application to delivery e-mails to | users of your application. Like the host we have set this value to | stay compatible with the Postmark e-mail application by default. | */  'port' => 587,  /* |-------------------------------------------------------------------------- | Global "From" Address |-------------------------------------------------------------------------- | | You may wish for all e-mails sent by your application to be sent from | the same address. Here, you may specify a name and address that is | used globally for all e-mails that are sent by your application. | */  'from' => array('address' => 'user@gmail.com', 'name' => 'user'),  /* |-------------------------------------------------------------------------- | E-Mail Encryption Protocol |-------------------------------------------------------------------------- | | Here you may specify the encryption protocol that should be used when | the application send e-mail messages. A sensible default using the | transport layer security protocol should provide great security. | */  'encryption' => 'tls',  /* |-------------------------------------------------------------------------- | SMTP Server Username |-------------------------------------------------------------------------- | | If your SMTP server requires a username for authentication, you should | set it here. This will get used to authenticate with your server on | connection. You may also set the "password" value below this one. | */  'username' => 'user@gmail.com',  /* |-------------------------------------------------------------------------- | SMTP Server Password |-------------------------------------------------------------------------- | | Here you may set the password required by your SMTP server to send out | messages from your application. This will be given to the server on | connection so that the application will be able to send messages. | */  'password' => 'YOUR ACCESS TOKEN',  /* |-------------------------------------------------------------------------- | Sendmail System Path |-------------------------------------------------------------------------- | | When using the "sendmail" driver to send e-mails, we will need to know | the path to where Sendmail lives on this server. A default path has | been provided here, which will work well on most of your systems. | */  'sendmail' => '/usr/sbin/sendmail -bs',  /* |-------------------------------------------------------------------------- | Mail "Pretend" |-------------------------------------------------------------------------- | | When this option is enabled, e-mail will not actually be sent over the | web and will instead be written to your application's logs files so | you may inspect the message. This is great for local development. | */  'pretend' => false,  'authmode' => 'XOAUTH2',  ); 

```

Read More

Monday, October 23, 2017

Gmail blocks login attempt from Python with app specific password

Leave a Comment

I'm trying to send an email from a Google account using Python's smtplib, but getting an error, and now I'm kind of at a loss. Google responds with the following: Please log in via your web browser and then try again. Learn more at https://support.google.com/mail/answer/78754.

The account has two factor authentication enabled, so I'm using an app specific password for my login. To my understanding, this should then work without enabling the setting for less secure apps, shouldn't it? I've been doing the same with another account while testing without a problem, but now I finally got the credentials for the proper account and there it won't accept the authentication.

I'm aware that there is a Python Gmail API thingy to use with OAuth, but if at all possible I don't want to include more packages and rewrite much, and I don't really want to enable the "less secure apps" setting either. Is there a way to get this working without either?

If it makes a difference, here is the code I use for sending email. As said before, this was working fine with another account, so I'm not sure if it's actually relevant.

def send_mail(to_address, subject, body):     smtp_user = "myaccount@domain.com"     smtp_password = "MyAppPasswordFromGoogle"     server = "smtp.gmail.com"     port = 587      msg = MIMEMultipart("alternative")     msg["Subject"] = subject     msg["From"] = smtp_user     msg["To"] = to_address     msg.attach(MIMEText(body, "html"))     s = smtplib.SMTP(server, port)     s.connect(server, port)     s.ehlo()     s.starttls()     s.ehlo()     s.login(smtp_user, smtp_password)     s.sendmail(smtp_user, to_address, msg.as_string())     s.quit() 

Edit: There is an interesting difference between the two accounts: on https://myaccount.google.com/lesssecureapps, my old (working) one says "this setting isn't available for accounts that have two factor authentication enabled", while the new one says "this setting is managed by your domain administrator", even though both use 2FA and it's also forced in both domains. So I suppose there is some setting that the domain admin has to change, but I don't know which one that would be.

3 Answers

Answers 1

I tried replicating exactly your case (with an account that has a two factor authentication enabled). After creating my app password, I used it in the code.

Anyway, I think your problem is this:

s = smtplib.SMTP(server, port) s.connect(server, port) 

You execute 2 times the connection.

Try with

s = smtplib.SMTP() s.connect(server, port) 

or just this

s = smtplib.SMTP(server, port) 

The entire code:

import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText   smtp_user = 'myUser@gmail.com' smtp_password = 'my16charactersAppPassword' server = 'smtp.gmail.com' port = 587 msg = MIMEMultipart("alternative") msg["Subject"] = 'Why,Oh why!' msg["From"] = smtp_user msg["To"] = "destinationUser@gmail.com" msg.attach(MIMEText('\nsent via python', 'plain')) s = smtplib.SMTP(server, port) s.ehlo() s.starttls() s.login(smtp_user, smtp_password) s.sendmail(smtp_user, "destinationUser@gmail.com", msg.as_string()) s.quit() 

Answers 2

I am just curious if you have enabled IMAP (despite of the fact that SMTP has nothing to do with IMAP)...

Here is an old list with many different solutions - Sending email through Gmail SMTP server with C#

Answers 3

Seems simple, but check to make sure Allow less secure apps is enabled.

Read More

Tuesday, August 8, 2017

How to read the Content Type header and convert into utf-8 while Gmail IMAP has utf8 and Outlook has ISO-8859-7?

Leave a Comment

So I get emails using imap from gmail and outlook.

Gmail encodes like this =?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpbA==?= and outlook encodes like this =?iso-8859-7?B?UmU6IOXr6+ft6er8IHN1YmplY3Q=?=

Unfortunately I did not find yet any solution that will help me make this into readable text. Instead I am messing with:

mb_convert_encoding($body, "UTF-8", "UTF-8");  

and

mb_convert_encoding($body, "UTF-8", "iso-8859-7"); 

but I am struggling to find a solution to solve this matter.

This is how I open the IMAP of my account (which has a lot of gmail and outlook messages)

$hostname = '{imappro.zoho.com:993/imap/ssl}INBOX'; $username = 'email@email.com'; $password = 'password';   /* try to connect */ $inbox = imap_open($hostname,$username ,$password) or die('Cannot connect to Zoho: ' . imap_last_error());  /* grab emails */ $emails = imap_search($inbox,'UNSEEN'); 

Any help?

4 Answers

Answers 1

Unfortunately I did not find yet any solution that will help me make this into readable text.

Solution Your strings are base64 encoded.

=?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpbA==?=

echo base64_decode('UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpbA=='); 

prints "Re: νέο εμαιλ new email"

=?iso-8859-7?B?UmU6IOXr6+ft6er8IHN1YmplY3Q=?=

echo base64_decode('UmU6IOXr6+ft6er8IHN1YmplY3Q='); 

prints out "Re: subject"

The answer is to use base64_decode in conjunction with your current solutions.

The way to identify base64 encoded text is that it's depicted as letters a-z, A-Z, numbers 0-9 along with two other characters (usually + and /) and it's usually right padded with =.

Answers 2

look here

   /* connect to gmail */     $hostname = '{imap.gmail.com:993/imap/ssl}INBOX';     $username = 'davidwalshblog@gmail.com';     $password = 'davidwalsh';      /* try to connect */     $inbox = imap_open($hostname,$username,$password) or die('Cannot connect to Gmail: ' . imap_last_error());      /* grab emails */     $emails = imap_search($inbox,'ALL');      /* if emails are returned, cycle through each... */     if($emails) {          /* begin output var */         $output = '';          /* put the newest emails on top */         rsort($emails);          /* for every email... */         foreach($emails as $email_number) {              /* get information specific to this email */             $overview = imap_fetch_overview($inbox,$email_number,0);             $message = imap_fetchbody($inbox,$email_number,2);              /* output the email header information */             $output.= '<div class="toggler '.($overview[0]->seen ? 'read' : 'unread').'">';             $output.= '<span class="subject">'.$overview[0]->subject.'</span> ';             $output.= '<span class="from">'.$overview[0]->from.'</span>';             $output.= '<span class="date">on '.$overview[0]->date.'</span>';             $output.= '</div>';              /* output the email body */             $output.= '<div class="body">'.$message.'</div>';         }          echo $output;     }       /* close the connection */     imap_close($inbox); 

for reading and decoding look here

<?php $hostname = '{********:993/imap/ssl}INBOX'; $username = '*********'; $password = '******';  $inbox = imap_open($hostname,$username,$password) or die('Cannot connect to server: ' . imap_last_error());  $emails = imap_search($inbox,'ALL');  if($emails) {     $output = '';     rsort($emails);      foreach($emails as $email_number) {         $overview = imap_fetch_overview($inbox,$email_number,0);         $structure = imap_fetchstructure($inbox, $email_number);          if(isset($structure->parts) && is_array($structure->parts) && isset($structure->parts[1])) {             $part = $structure->parts[1];             $message = imap_fetchbody($inbox,$email_number,2);              if($part->encoding == 3) {                 $message = imap_base64($message);             } else if($part->encoding == 1) {                 $message = imap_8bit($message);             } else {                 $message = imap_qprint($message);             }         }          $output.= '<div class="toggle'.($overview[0]->seen ? 'read' : 'unread').'">';         $output.= '<span class="from">From: '.utf8_decode(imap_utf8($overview[0]->from)).'</span>';         $output.= '<span class="date">on '.utf8_decode(imap_utf8($overview[0]->date)).'</span>';         $output.= '<br /><span class="subject">Subject('.$part->encoding.'): '.utf8_decode(imap_utf8($overview[0]->subject)).'</span> ';         $output.= '</div>';          $output.= '<div class="body">'.$message.'</div><hr />';     }      echo $output; }  imap_close($inbox); ?> 

Look here for great tutorial on email structure, and function to extract it.

Answers 3

If you want to decode header elements, there is a PHP function for that: imap_mime_header_decode().

Also, you will need some MIME parser class to decode multipart messages.

Answers 4

To get the headers, you would pass your stream ($inbox) to imap_headers(). There are lots of values you can get in the response, full list: imap_headerinfo

For the actual messages, plain text can be read using imap_body(), passing the stream and the number of the message you want (in $emails after your search). Getting an html/multipart email is a bit trickier. First you need imap_fetchstructure(), which identifies the parts of the message, then imap_fetchbody() to get the piece you are interested in.

Once you have a result from imap_fetchbody(), if you still need to adjust the encoding, it could be done at this point.

Read More

Thursday, April 20, 2017

Error: Cannot attach empty file in GMAIL app using File provider

Leave a Comment

I am trying to attach a pdf file in gmail app. I have read this and this (applied solution) I am trying as;

public static void attachFile(Context ctx) {     String TAG = "Attach";     File documentsPath = new File(ctx.getFilesDir(), "documents");     Log.i(TAG,"documentsAbsolutePath Output");     Log.i(TAG, documentsPath.getAbsolutePath().toString());     File file = new File(documentsPath, "sample.pdf");     if ( file.exists() ) {         Toast.makeText(ctx, "Exits", Toast.LENGTH_LONG).show();     }else{         Toast.makeText(ctx, "Not Exist", Toast.LENGTH_LONG).show();     }     Log.i(TAG,"file Output");     Log.i(TAG, file.toString());     Log.i(TAG, String.valueOf(file.length()));     Uri uri = FileProvider.getUriForFile(ctx, "com.example.fyp_awais.attachfiletest2.fileprovider", file);     Log.i(TAG,"URI Output");     Log.i(TAG,uri.toString());     Intent intent = ShareCompat.IntentBuilder.from((Activity) ctx)             .setType("application/pdf")             .setStream(uri)             .setChooserTitle("Choose bar")             .createChooserIntent()             .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);     ctx.startActivity(intent); } 

Outputs

documentsAbsolutePath Output /data/data/com.example.fyp_awais.attachfiletest2/files/documents  file Output /data/data/com.example.fyp_awais.attachfiletest2/files/documents/sample.pdf  0  URI Output  content://com.example.fyp_awais.attachfiletest2.fileprovider/pdf_folder/sample.pdf 

Menifest

<provider     android:name="android.support.v4.content.FileProvider"     android:authorities="com.example.fyp_awais.attachfiletest2.fileprovider"     android:exported="false"     android:grantUriPermissions="true">     <meta-data         android:name="android.support.FILE_PROVIDER_PATHS"         android:resource="@xml/filepath" /> </provider> 

FilePath.xml

<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">     <paths xmlns:android="http://schemas.android.com/apk/res/android">         <files-path name="pdf_folder" path="documents/"/>     </paths> </PreferenceScreen 

A pdf file is saved in Galaxy Core Prime\Phone\documents. (file size: 53.7KB)

But it gives

Cannot attach empty file.

enter image description here

I am confused with folder-name in this line <files-path name="pdf_folder" path="documents/"/>. The file is in the \Phone\documents. Then why folder name?

Edit 1

Tried to replace setType(application/pdf) with setType("message/rfc822") But did not work. Any help?

6 Answers

Answers 1

Send the file in URI format like this:

Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);         emailIntent.setData(Uri.parse("mailto:"));         emailIntent.setType("application/image");         emailIntent.putExtra(Intent.EXTRA_EMAIL, TO);         emailIntent.putExtra(Intent.EXTRA_CC, CC); ArrayList<Uri> uris = new ArrayList<>();         //convert from paths to Android friendly Parcelable Uri's         uris.add(frontImageUri);         uris.add(backImageUri);         emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); startActivity(Intent.createChooser(emailIntent, "Send mail...")); 

Answers 2

if it's ok To send Zip then try this way

String fileNameStor_zip = Environment.getExternalStorageDirectory() + "/" + fileName + ".zip";

String[] path = { your 1st pdf File Path, your 2nd pdf File Path};

Compress compress = new Compress(path, fileNameStor_zip);

compress.zip();

URI = Uri.parse("file://" + fileNameStor_zip);

Provide your Gmail Intent

intent.putExtra(Intent.EXTRA_STREAM, URI);

Answers 3

Uri contentUri = FileProvider.getUriForFile(this, "com.mydomain.fileprovider", newFile); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); i.setData(contentUri); 

Answers 4

String filename="my_file.vcf";  File filelocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), filename); Uri path = Uri.fromFile(filelocation);  Intent emailIntent = new Intent(Intent.ACTION_SEND); // set the type to 'email' emailIntent .setType("vnd.android.cursor.dir/email"); String to[] = {"asd@gmail.com"}; emailIntent .putExtra(Intent.EXTRA_EMAIL, to); // the attachment emailIntent .putExtra(Intent.EXTRA_STREAM, path); // the mail subject emailIntent .putExtra(Intent.EXTRA_SUBJECT, "Subject"); startActivity(Intent.createChooser(emailIntent , "Send email...")); 

Answers 5

You have to grant the permission to access storage for gmail.

Answers 6

In case it helps- here's what I do in an app debug function with a few files, it shouldn't really be any different. I do copy/export them into a user-public folder first before attaching them, and make them world readable.

 if (verifyStoragePermissions(c)) {         final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);         intent.setType("text/plain");         intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"recipient@email.address"});         intent.putExtra(Intent.EXTRA_SUBJECT, "Email Subject");          //build up message         ArrayList<Uri> uris = new ArrayList<>();         StringBuilder content = new StringBuilder();         content.append(                 String.format(                         c.getString(R.string.message_log_upload_email_body) +                                 "\n\nmodelDesc:%s \n\nmanuf:%s \n\naId: %s,\n\nhIid: %s,\n\nfbId: %s.",                         Build.MODEL, Build.MANUFACTURER, getSomeVar1(), getSomeVar2(), getSomeVar3())         );         content.append("\n\nMy logged in account id is: ").append(getAccountId(c)).append(".");         content.append("\n\nHere's an overview of my attachments:\n");          for (String s : addresses) {             File f = new File(s);             //noinspection ResultOfMethodCallIgnored             f.setReadable(true, false);             Uri add = Uri.fromFile(f);             //add attachment manifest             content.append(String.format(Locale.UK, "|->  %s (%.3f kb)\n", f.getName(), (float) f.length() / 1024));             uris.add(add);         }         //attach the things         intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);         //set content/message         intent.putExtra(Intent.EXTRA_TEXT, content.toString());         c.startActivity(intent);     } } 

addresses is a String[] param to that function. I build it up by making the functions I use to export the files return arrays of strings of the addresses of the files they've exported - as I initially store the files in my app's private storage

Read More

Tuesday, January 31, 2017

Can you and how do you embed images in an email when using the Gmail API?

Leave a Comment

When creating a message and using it to create a draft or email using the Gmail API, can you have an image embedded in the body? I'm looking to have the image data actually embedded similar to how copying and pasting an image (the actual data, not the link) into a Gmail email will place the image right in the content.

Can it be done like this or do I need to upload the image to some other location and use HTML to embed the image in the email? Any pointers on how to do it?

1 Answers

Answers 1

The short answer is that you would do this the same way you would for any email service.

The long answer is that you need to create a multipart/related message, where one part is the HTML content of the email and the other part is the image. The image part contains a Content-ID header that specifies an ID for the image, and the HTML image tag references that ID in the src attribute using the format cid:ID_HERE.

An example of how to construct such an email in Python is here: http://stackoverflow.com/a/1633493

P.S. - A great way to see how emails are constructed is to look at the raw message. You can look at the raw message for a given email in Gmail by clicking the drop down arrow next to the message and selecting "Show original".

Read More

Monday, August 8, 2016

Gmail API configuration issue (in Java)

Leave a Comment

Here is my Gmail service configuration/factory class:

import java.io.File; import java.io.IOException; import java.security.GeneralSecurityException;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment;  import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.HttpRequestInitializer; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.services.gmail.Gmail; import com.google.api.services.gmail.GmailScopes;  public class GmailServiceFactoryBean {      private @Autowired Environment env;      private final NetHttpTransport transport;     private final JacksonFactory jacksonFactory;      public GmailServiceFactoryBean() throws GeneralSecurityException, IOException {         this.transport = GoogleNetHttpTransport.newTrustedTransport();         this.jacksonFactory = JacksonFactory.getDefaultInstance();     }      public Gmail getGmailService() throws IOException, GeneralSecurityException {         return new Gmail.Builder(transport, jacksonFactory, getCredential())                 .setApplicationName(env.getProperty("gmail.api.application.name")).build();     }      private HttpRequestInitializer getCredential() throws IOException, GeneralSecurityException {         File p12File = new File(this.getClass().getClassLoader().getResource("google-key.p12").getFile());          Credential credential = new GoogleCredential.Builder()             .setServiceAccountId(env.getProperty("gmail.api.service.account.email"))             .setServiceAccountPrivateKeyId(env.getProperty("gmail.api.private.key.id"))             .setServiceAccountPrivateKeyFromP12File(p12File)             .setTransport(transport)             .setJsonFactory(jacksonFactory)             .setServiceAccountScopes(GmailScopes.all())             //.setServiceAccountUser(env.getProperty("gmail.api.user.email"))             .build();          credential.refreshToken();          return credential;     }  } 

Here is my inner mailing service that uses previous bean under the hood:

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.List; import java.util.Properties;  import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage.RecipientType;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service;  import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64; import com.google.api.services.gmail.Gmail; import com.google.api.services.gmail.model.Message; import com.example.factory.GmailServiceFactoryBean; import com.example.service.MailService; import com.example.service.exception.MailServiceException;  @Service public class MailServiceImpl implements MailService {      private @Autowired GmailServiceFactoryBean gmailServiceFactoryBean;     private @Autowired Environment env;      @Override     public void send(com.example.model.Message message, String recipient) throws MailServiceException {         try {             Gmail gmailService = gmailServiceFactoryBean.getGmailService();             MimeMessage mimeMessage = createMimeMessage(message, recipient);             Message gMessage = createMessageWithEmail(mimeMessage);             gmailService.users().messages().send("me", gMessage).execute();         } catch(MessagingException | IOException | GeneralSecurityException e) {             throw new MailServiceException(e.getMessage(), e.getCause());         }     }      @Override     public void send(com.example.model.Message message, List<String> recipients) throws MailServiceException {         for (String recipient : recipients) {             send(message, recipient);         }     }      private MimeMessage createMimeMessage(com.example.model.Message message, String recipient) throws MessagingException {         Session session = Session.getDefaultInstance(new Properties());          MimeMessage email = new MimeMessage(session);         InternetAddress toAddress = new InternetAddress(recipient);         InternetAddress fromAddress = new InternetAddress(env.getProperty("gmail.api.service.account.email"));          email.setFrom(fromAddress);         email.addRecipient(RecipientType.TO, toAddress);         email.setSubject(message.getTitle());         email.setText(message.getContent(), env.getProperty("application.encoding"));          return email;     }      private Message createMessageWithEmail(MimeMessage email) throws MessagingException, IOException {         ByteArrayOutputStream baos = new ByteArrayOutputStream();         email.writeTo(baos);         return new Message().setRaw(Base64.encodeBase64URLSafeString(baos.toByteArray()));     } } 

When I execute method send(Message message, String recipient) of class MailServiceImpl I get following response:

400 Bad Request {   "code" : 400,   "errors" : [ {     "domain" : "global",     "message" : "Bad Request",     "reason" : "failedPrecondition"   } ],   "message" : "Bad Request" } 

Does anyone know what's wrong?

2 Answers

Answers 1

For GMail API to work, you have to "Delegate domain-wide authority to the service account" within your Google Apps account.

Service account doesn't represent a human Google account. You also can't delegate authority to whole Google domain(***@gmail.com).

The other way out could be with OAuth 2.0 for Web Server Applications or Java Mail api

For more do check: GMail REST API: Using Google Credentials Without Impersonate

Answers 2

Check if you have enabled gmail to send mails using 3rd party applications.

Go to my account ->Sign in and Security -> Connected Apps now scroll to the bottom of the page you will get Less secure apps ->change it to on !! Hope this will work

Read More

Thursday, April 14, 2016

Easy reverse proxy for serving images over ssl

Leave a Comment
This summary is not available. Please click here to view the post.
Read More