Missing email using JavaMail on Google App Engine - java

I have this really weird problem and I'm not able to find a solution... I hope you can help me...
I'm working in Google App Engine to build my App (lets call it "MyApp"), to test, I have a cloned app renamed as "sandbox-MyApp".
I need to allow my users send a mail with some data, so I have a form where they can fill some information that will be added to the message.
I've working with this scenario a long time ago, but now I'm having issues, because, for some reason, my out-coming mails are not being received by the recipients...
It's a really weird thing about this, because, I can send one or two mails without problem, but after that, they suddenly stop, and after some code-changes, they work again.
I'm using Java.Mail to do the work,
I'm trying to send a simple HTML,
My "from" address is something like "userName#sandbox-myApp.appspotmail.com"
My Subject its something like: "Hello userName! There is some important message for you"
The message it's really simple, includes an image logo (served by an https://sandbox-myApp.appspot.com/img/logo.png), an invitation text and a single link to my app URL... (https://sandbox-myApp.appspot.com/)
My code it's real simple, based on the Google Documentation.
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(senderAddress, MimeUtility.encodeText(senderLabel, "UTF-8", "B"), "UTF-8"));
msg.addRecipient(javax.mail.internet.MimeMessage.RecipientType.TO, new InternetAddress(receiverAddress, receiverLabel, "UTF-8"));
if(responseAddress != null && !responseAddress.trim().isEmpty()){
msg.setReplyTo(new Address[] {
new InternetAddress(responseAddress, MimeUtility.encodeText(senderLabel, "UTF-8", "B"))
});
}
msg.setSubject(MimeUtility.encodeText(subject, "UTF-8", "B"), "UTF-8");
msg.setContent(msgBody, "text/html;charset=UTF-8");
Transport.send(msg);
I've tried changing "from" to something like "app_admin#mydomain.com" and it works for a while, but after some mails (about 5 or 6), stop working too.
Most shocking thing: There aren't any error message on logs... The Cuota Viewer counts every sent mail (so I suppose it must being blocked somewhere else),
I've modiffied the message to omit any URL on the body and It works better, but I need to include it!.

Problem is tracked on https://code.google.com/p/googleappengine/issues/detail?id=12786
Workaround which worked for my application is to not use appspot.com domain.
Register custom domain for the application and then mails to the application using the custom domain work.

Related

Google Drive API - OAuth2.0: How to Automate Authentication Process? Doubts and Questions

I'm trying to integrate Google APIs inside a project (Thesis project) and I have some doubts and questions. So, here it is the scenario:
I wrote a back-end application in Java that runs solely from a command-line and has absolutely no interaction with a user. Its goal is to allow communication and interaction between sensors and actuators. Everything works great. Now I'd like to integrate something in order to let the sensors backup data both with a certain periodicity and due to some detected threshold value. So I thought, why not trying with Google Drive. The first very useful links have been:
https://developers.google.com/drive/web/quickstart/quickstart-java
https://developers.google.com/accounts/docs/OAuth2InstalledApp
Quick start examples work like a charm. However it requires quite a bit of settings: create a project inside the Developer Console (therefore an account), enable Drive API, then create a Client ID and a Client Secret. Once you've done these steps, you can hard-coded client ID and secret to form the request URL for google drive. Then you're kindly asked to enter the url in a browser, log in if you're not, accept and finally copy and paste into your console the authorization code for obtaining an access token. Wow, quite a security proccess. But hey, I completely agree with it, above all in a scenario where we have either a web app, a smartphone app or a web service that needs users' authentication and authorization in order to let the app doing its job by accessing someone else account. But in my case, I just would like that sensors will backup data on my google drive.
These facts lead to my first question: in order to use Google APIs (Drive in this case), do I have to create a project anyway? Or is there another approach? If I'm not wrong, there aren't other ways to create a client Id and secret without creating a project inside the Developer Console. This puzzles me a lot. Why should I create a project to use basically some libraries?
So, let's assume the previous as justifiable constraints and move on the real question: how to automate the authentication process? Given my scenario where a sensor (simply a Java module) want to backup data, it would be impossible to complete all that steps. The google page about OAuth 2.0 has a great explanations about different scenarios where we can embed the authentication procedure, included one for "devices with limited input capabilities". Unluckily, this is more complicated then the others and requires that "The user switches to a device or computer with richer input capabilities, launches a browser, navigates to the URL specified on the limited-input device, logs in, and enters the code." (LOL)
So, I didn't give up and I ended up on this post that talks about OAuth Playground: How do I authorise an app (web or installed) without user intervention? (canonical ?). It really looks like as a solution for me, in particular when it says:
NB2. This technique works well if you want a web app which access
your own (and only your own) Drive account, without bothering to write
the authorization code which would only ever be run once. Just skip
step 1, and replace "my.drive.app" with your own email address in step
5.
However if I'm not wrong, I think that OAuth Playground it's just for helping test and debug projects that use Google APIs, isn't it? Moreover, Google drive classes such as GoogleAuthorizationCodeFlow and GoogleCredential (used inside the Java quick start example) always need Client ID, Client Secret and so on, which brings me to point zero (create a project and do the whole graphical procedure).
In conclusion: is there a way to avoid the "graphical" authentication interaction and convert it into an automated process using only Drive's APIs without the user intervention? Thanks a lot, I would be grateful for any tip, hint, answer, pointer :-)
This is just a snippet of code that I wrote thanks to pinoyyid suggestions. Just to recap what we should do in this case (when in your program there isn't a user interaction for completing all the Google GUI authentication process). As reported in https://developers.google.com/drive/web/quickstart/quickstart-java
Go to the Google Developers Console.
Select a project, or create a new one.
In the sidebar on the left, expand APIs & auth. Next, click APIs. In the list of APIs, make sure the status is ON for the Drive API.
In the sidebar on the left, select Credentials.
In either case, you end up on the Credentials page and can create your project's credentials from here.
From the Credentials page, click Create new Client ID under the OAuth heading to create your OAuth 2.0 credentials. Your application's client ID, email address, client secret, redirect URIs, and JavaScript origins are in the Client ID for web application section.
The pinoyyd post is neater and get straight to the point: How do I authorise a background web app without user intervention? (canonical ?)
Pay attention to step number 7
Finally the snippet of code is very simple, it's just about sending a POST request and it's possible to do that in many ways in Java. Therefore this is just an example and I'm sure there is room for improvements ;-)
// Both to set access token the first time that we run the module and in general to refresh the token
public void sendPOST(){
try {
URL url = new URL("https://www.googleapis.com/oauth2/v3/token");
Map<String,Object> params = new LinkedHashMap<>();
params.put("client_id", CLIENT_ID);
params.put("client_secret", CLIENT_SECRET);
params.put("refresh_token", REFRESH_TOKEN);
params.put("grant_type", "refresh_token");
StringBuilder postData = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
BufferedReader in_rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
// Read response body which should be a json structure
String inputLine;
StringBuilder responseBody = new StringBuilder();
while ((inputLine = in_rd.readLine()) != null) {
responseBody.append(inputLine);
}
in_rd.close();
//Parsing Response --> create a json object
JSONObject jsonResp = new JSONObject(responseBody);
//Modify previous access token String
ACCESS_TOKEN = jsonResp.getString("access_token");
}
catch(MalformedURLException ex_URL){
System.out.println("An error occured: " + ex_URL.getMessage());
}
catch(JSONException ex_json) {
System.out.println("An error occured: " + ex_json.getMessage());
}
catch(IOException ex_IO){
System.out.println("An error occured: " + ex_IO.getMessage());
}
} //end of sendRefreshPOST method
Hope this snippet of code will help others that will face the same situation !
I wrote the SO post at How do I authorise an app (web or installed) without user intervention? (canonical ?)
What it describes is indeed the solution to your use-case. The key bit you'd missed is step 7 where you enter the details of your own application into the OAuth Playground. From that point, the playground is impersonating your app and so you can do the one-time authorization and obtaining a refresh token.

Apache Camel reading unread mail from gmail account

Just tried learning Apache Camel.
I am trying to read gmail inbox unread mail.
I got the code snippet while searching but not able to get success from it.
if someone point out the mistake,
PollingConsumer pollingConsumer = null;
CamelContext context = new DefaultCamelContext();
Endpoint endpoint = context.getEndpoint("imaps://imap.gmail.com?username=" + mailId + "&password=" + password + "&delete=false&peek=false&unseen=true&consumer.delay=6000&closeFolder=false&disconnect=false");
System.out.println("end point:"+endpoint);
pollingConsumer = endpoint.createPollingConsumer();
System.out.println("polling consumer:"+pollingConsumer);
pollingConsumer.start();
pollingConsumer.getEndpoint().createExchange();
System.out.println("Exchange is created:");
Exchange exchange = pollingConsumer.receive();
System.out.println("pollingConsumer.receive()");
pollingConsumer.receive(); is getting blocked, I have unread mail in my mailbox.
Also I tried pollingConsumer.receive(6000); but it returns null.
I enable IMAP access in Gmail settings. is there any thing I am missing?
Let me write the solution, It will help someone facing similar issue .
Actually I have added java mail jar, but imap jar was missing and it was not displaying any error for this.
That is why I was not able to figure out the actual cause.
After browsing the parameters of "imaps://imap.gmail.com", I came across "debugMode" parameter which by default is false. when I added that parameter with value true, then it complained of missing jar on my console. After adding that jar thinks work perfectly.
Thanks for help.

Adding to, cc,subject in Desktop.mail(uri)

I am a beginner of using Desktop.mail(URI) class, so I am looking for a way to add to, cc and subject to the mail when triggered from the program.
String mailTo = "test#domain.com";
String cc = "test2#domain.com";
String subject = "firstEmail";
String body = "the java message";
URI uriMailTo = new URI(mailTo,cc,subject,body);
Desktop desktop;
desktop = Desktop.getDesktop();
desktop.mail(uriMailTo);
can any one suggest any tutorials to learn this process, because I am looking for even more functions like receiving the data back from the outlook to the Java program.
Thanks in advance for help!
The Desktop.mail() function is a utility method for launching whatever mail program may exist in the users system (if any). You have (very) limited capability of controlling the actual mail message to be (eventually) sent, and once the mail client is displayed you're pretty much done - aka you wont be getting any feedback on what message was actually sent or wether it succeeded.
If you need this level of control then you should be using the JavaMail API, which does a lot of what you seem to need.
If you are stuck with using the Desktop mail client, then you might want to read up on RFC 2368. It describes all the fields that can be included in a mailto URI. So, you will be able to populate the message, but you won't get feedback on wether it was successfully sent or not:
mailto:joe#example.com?cc=bob#example.com&body=hello+world
A code example of constructing your URI (which is incorrect btw):
final String mailURIStr = String.format("mailto:%s?subject=%s&cc=%s&body=%s",
mailTo, subject, cc, body);
final URI mailURI = new URI(mailURIStr);
Where the substituted should be URL encoded if necessary.

Send mail to javamail (or ftpmail?) and save attachment

I have been searching for a solution for my problem for a while now.
It work to send mail through javamail, and get an attachment to save. But the problem is that I cant get swedish letters like 'åäö' to show. The file is saved in ISO-Latin-1. (Filename is like "ISO-8859-1HwhajkAWJKHWo..."). I have tried to decode it and every solution that I've found searching.
But it wont work, doesn't matter how much I try, it wont work. Anyone have a similar problem?
And then I was thinking is it possible to send an email to ftpmail(?) and using a java program to catch the attachment in the file and save it. With all the letters copied correctly (åäö).
Or does anyone have another solution to fix this? Send an email to a server who will look through the mail and if it got attachment, save it.
Really, javax.mail works fine with UTF-8. You have to set it for subject, content and text attachments.
MimeMessage message = new MimeMessage(session);
message.setSubject(subject, "UTF-8");
message.setHeader("Content-Type", "text/plain; charset=UTF-8");
message.setText(body, "UTF-8");

Sending images by mail

I've written a mail that'll send emails with images as attachments. The images are displaying in yahoo and gmail. But hotmail is displaying a square grey box wherever there should be an image. The following is the code that builds the image. Of course I'm reffering to it in the mail using cid. Thanks a lot in advance.
l_embedImage = new MimeBodyPart();
l_dataSource = new FileDataSource(new File(l_imagesBaseDirectory + "/" + l_completeImagePath));
l_dataHandler = new DataHandler(l_dataSource);
l_embedImage.setDataHandler(l_dataHandler);
l_embedImage.setHeader("Content-ID", "<" + l_cid + ">");
l_embedImage.setHeader("Content-Type", "image/gif");
l_embedImage.setHeader("discrete-type","image");
l_embedImage.setHeader("content-transfer-encoding", "base64");
p_multipart.addBodyPart(l_embedImage);
I was having troubles with delivering e-mails until I went through the steps to become a trusted mail server.
Check out step 4 ("Authenticate your outbound e-mail: Publish Sender Policy Framework (SPF) records") in the following URL:
http://postmaster.msn.com/Guidelines.aspx
I think that hotmail doesn't load them automatically, the user should agree on this message first:
Attachments, pictures, and links in
this message have been blocked for
your safety. Show content
As usual Microsoft must complete programmers life ;)

Categories

Resources