Email Notification Using JavaMail - google-app-engine

I was trying a method to implement email notification Using JavaMail.I wrote the code and there is no error. But no email has been sent.
I am using GAE with JSF2.
Properties props = new Properties();
javax.mail.Session session1 = javax.mail.Session.getDefaultInstance(props, null);
String msgBody = "This is a test mail";
try {
System.out.println("Email notification is sending");
Message msg = new MimeMessage(session1);
msg.setFrom(new InternetAddress("myGmailId1#gmail.com", "Example.com Admin"));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress("myGmailId2#gmail.com", "Mr. User"));
msg.setSubject("Your Example.com account has been activated");
msg.setText(msgBody);
Transport.send(msg);
System.out.println("Email notification has been sent");
} catch (AddressException e) {
// ...
} catch (MessagingException e) {
// ...
}
Where I went wrong?

Check that your sender e-mail address either registered as the administrator of your app, or the e-mail address of the current user that's logged in to the app.
According to the App Engine Mail API documentation:
For security purposes, the sender address of a message must be the
email address of an administrator for the application or any valid
email receiving address for the app (see Receiving Mail). The sender
can also be the Google Account email address of the current user who
is signed in, if the user's account is a Gmail account or is on a
domain managed by Google Apps.

Related

javax.mail.MessagingException: A3 BAD User is authenticated but not connected

I am trying to read mail from exchange server using IMAP protocol. I have implemented the code. But following exception occurs while executing the code.This exception occurs occasionally, I didn't get the reason why this is happening.
javax.mail.MessagingException: A3 BAD User is authenticated but not connected.;
nested exception is:
com.sun.mail.iap.BadCommandException: A3 BAD User is authenticated but not connected.
at com.sun.mail.imap.IMAPFolder.open(IMAPFolder.java:958)
at agent.client.attributeGroups.SendReceive.readMailAndReply(SendReceive.java:115)
at agent.client.attributeGroups.MailQueue.calculateTime(MailQueue.java:45)
at agent.client.MainClass$1.run(MainClass.java:72)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
code:
Properties props = new Properties();
props.put("mail.imap.auth", "true");
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imap.host", "outlook.office365.com");
props.put("mail.imap.port", "993");
props.put("mail.transport.protocol", "imap");
props.put("mail.imap.auth.plain.disable", true);
props.put("mail.imap.auth.ntlm.disable", true);
props.put("mail.imap.auth.gssapi.disable", true);
//Get session object by passing credentials.
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator(){
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
mailId, mailPass);}});
//Creating IMAP store and connecting it to Mailbox using credentials.
store = session.getStore("imap");
store.connect(mailId, mailPass);
//Getting mailbox mails.
inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);
int totalMailCount = inbox.getMessageCount();
//Reading all mails to Message array.
Message[] messages = inbox.getMessages(1, totalMailCount);
for (Message mail : messages)
{
Address[] fromAddresses = mail.getFrom();
String mailFrom = fromAddresses[0].toString();
String mailSubject = mail.getSubject();
System.out.println(mailFrom);
System.out.println(mailSubject);
mail.setFlag(Flags.Flag.DELETED,true);
}
}
}
Please suggest me suggestions to resolve this exception.
I have also faced that issue
You didn't close the connection,it always in open.
If you use Store and Inbox it always authenticated but not connected
It is authentication successfully but not connected because session is paradise.
You need to add below lines to your code.
First close the inbox after read
inbox.close(true);
Next close the store Connection
store.close();
If you close the estabilished connection correctly then it will connected according to the session.
Hope this really helpful for you
My problem was because I use a process to move emails from inbox to another different folder. I did it in batches because move big quantities emails throw Timeout exception, so I try to move small cquantities and I avoid the Timeout exception but started to get the BadCommandException: A2 BAD User is authenticated but not connected Exception. So I looking by an amount that worked for me. I got the idea base on this post
https://github.com/mscdex/node-imap/issues/689
It is a Microsoft's mechanism to shut down chatty clients. The
solution would be to login to this account less frequently.
It is due to a bug in the IMAP implementation. If the client presents a valid user name but an invalid password, the server
accepts the login, but subsequent commands fail with the
aforementioned error message.
It is a shared mailbox and you are using incorrect login scheme. Use Username#DomainName\SharedMailboxAlias for O365
This error message appears to be triggered when you've connected to an Exchange mail server (such as Office365) with a valid user and the correct password, but that user doesn't have permissions for the type of connection you made.
For example, I've seen several cases now where an IMAP connection was made, the system logged in with valid credentials, and the moment the first IMAP command was sent, the server said, "User is authenticated but not connected" and closed the connection.
To correct it, we went into the Exchange server or Office365 mail settings and ensured that the IMAP permission was checked for that user.
First,you should check the mail.imap.host value is equivalent to the email address's server.
If you use outlook OC
If true,you could then try to change the protocol to IMAPS
I hope the snippets that set of properties can help many that want to recieve mails.
sysProperties.put("mail.imap.starttls.enable", true);
MailSSLSocketFactory sf = null;
try {
sf = new MailSSLSocketFactory();
} catch (GeneralSecurityException e1) {
e1.printStackTrace();
}
sf.setTrustAllHosts(true);
sysProperties.setProperty("mail.imaps.auth.plain.disable", "true");
sysProperties.setProperty("mail.imaps.auth.ntlm.disable", "true");
sysProperties.put("mail.imap.ssl.socketFactory", sf);
sysProperties.setProperty("mail.imap.port", instance.getConfigPropertiesValue(configProperties, "mail.imap.port"));
sysProperties.setProperty("mail.imap.ssl.socketFactory.port", "993");
Session session = Session.getDefaultInstance(sysProperties, null);
Store store = null;
store = session.getStore("imaps");
store.connect("mail.serverhost", "mail.serverport"), "mail.username,"mail.password"));
Could it be related to your exchange settings? I ran into this error with imap and outlook.office365.com. I tried to set up the same account in Outlook to make sure it was working in general. Although I was able to add the account, when I actually tried to look at the inbox Outlook became unresponsive. So in my case, it was a problem with the account in general, not with how I was trying to connect.
It appears to be a bug in the office365 server. It's telling you that your password was wrong.

Gmail (for business) API doesn't allow to send email from Alias?

I want to email my customers using different "roles" (e.g. info# , customer-support#, tech-support#, no-reply#).
I've tried 2 approaches:
Multiple "users"/accounts in my Gmail for business application.
Single gmail
account with multiple aliases.
I started by setting up a Service Account with global delegation for my Gmail for Business application.
To test that it works, I've set up 2 users: lev#mydomain.com and root#mydomain.com. Indeed, I can successfully send email both from lev# and root#.
However, when I tried adding 5 distinct user accounts for my application, Gmail got paranoid of bots/abuse and asked me to prove that all the accounts are "human" including setting up passwords, signing in and SMS-text validation via phone. Moreover, they require different phones for different accounts to prove it's a different person. So the setup of the accounts becomes a major issue.
I also want to avoid creating multiple accounts since I'm paying for each one, and since semantically, all the roles are just a single account. So aliases seem like a better idea.
The problem is that when I'm trying to send email and set the "from" field to the alias (e.g. from:no-reply#mydomain.com), I'm getting the following exception:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Delegation denied for root#mydomain.com",
"reason" : "forbidden"
} ],
"message" : "Delegation denied for root#mydomain.com"
}
Anyone faced and solved this issue?
The authentication/credential code is as follows:
/*
* Set up a hashmap HashMap<String, Gmail> gmailServiceByAccount where
* gmailServiceByAccount.get(emailAccount) contains an authorized Gmail service
*/
private void prepareService(String emailAccount) throws Exception {
if (gmailServiceByAccount.containsKey(emailAccount)) {
return;
}
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(Config.getInstance().getProperty(Config.gmail_service_account))
.setServiceAccountPrivateKeyFromP12File(new File(Config.getInstance().getPathToGmailCredential()))
.setServiceAccountScopes(Arrays.asList(GmailScopes.GMAIL_COMPOSE))
.setServiceAccountUser(emailAccount)
.build();
gmailServiceByAccount.put(
emailAccount,
new Gmail.Builder(httpTransport, jsonFactory, credential)
.setApplicationName(Config.getInstance().getProperty(Config.google_client_api_application_name))
.build());
}
And the code which sends the email is as follows:
/**
* Send an email using the parameters provided.
*
* #param fromPersonalName : the free text description of the "from" address (e.g. "Customer Suppport" or "No Reply").
* #param fromAddress : the email address of the sender, the mailbox account (e.g. customer-support#mydomain.com).
* #param to : the email address of the recepient.
* #param subject : Subject of the email.
* #param htmlContent : (may be null) The HTML-styled body text of the email.
* #param plainTextContent : (may be null) The plain text body of the email (e.g if the customer email client does not support or disables html email).
*/
public void sendMail(String fromPersonalName, String fromAddress, String to, String subject, String htmlContent, String plainTextContent)
throws Exception {
prepareService(fromAddress);
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage email = new MimeMessage(session);
InternetAddress tAddress = new InternetAddress(to);
InternetAddress fAddress = new InternetAddress(fromAddress);
fAddress.setPersonal(fromPersonalName);
email.setFrom(fAddress);
email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress);
email.setSubject(subject);
Multipart multiPart = new MimeMultipart("alternative");
if (!StringValidation.isEmpty(plainTextContent)) {
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(plainTextContent, "text/plain");
textPart.setHeader("Content-Type", "text/plain; charset=\"UTF-8\"");
multiPart.addBodyPart(textPart);
}
if (!StringValidation.isEmpty(htmlContent)) {
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(htmlContent, "text/html; charset=\"UTF-8\"");
multiPart.addBodyPart(htmlPart);
}
email.setContent(multiPart);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
email.writeTo(bytes);
String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
Message message = new Message();
message.setRaw(encodedEmail);
gmailServiceByAccount.get(fromAddress).users().messages().send(fromAddress, message).execute();
}
After additional research, it looks like the only option is to have multiple users.
The code I've posted indeed works for multiple users, but not for anything else.
I've tried multiple options including aliases and group email accounts. I'd either get "delegation denied" or "invalid grant" errors.
I've tried contacting Google For Business customer and tech support, but they don't support the API.
There's a great workaround to creating several users without having to go through phone validation. Just specify these users as "existing users" when you're signing into Google For Business initially, and activate them before you even transfer the domain.
For the account I've created without pre-existing users, I had to ask my friend's phones for phone validation.
You can now send emails using aliases as long as those aliases are defined for the user whose login credentials you're using.
This works for the Gmail for business only.
Setting up aliases to non-existent address can be tricky, so have a look at this how to set up a catch-all routing:
catchall-for-domain-aliases-in-gsuite-gmail
Just additionally to Ladi's post, it seem to be easier to setup now. Make an alias account and configure it so you can send emails (https://support.google.com/domains/answer/9437157?hl=en&ref_topic=6293345) and set the 'from' field on the message to the alias (but still use 'me' on the API call)

not receive email in google app engine java

I'm writing code for receive email and change into todo. I received fresh email and converted todo but I sent forward email or reply email app engine not receive the email. What's the problem. I used session and getdefaultinstance that's all rest of the code same as receive email code.please do the needful.thanks
IN SERVLET Properties props = new Properties();
Session email = Session.getDefaultInstance(props, null);
try
{
MimeMessage message = new MimeMessage(email,req.getInputStream());
String summary = message.getSubject();
String description = getText(message);
Address[] addresses = message.getFrom();
User user = new User(addresses[0].toString(), "gmail.com");
Date date =new Date();
DaoComments.INSTANCE.add(addresses[0].toString(),lid,date,description,"selcom‌​ment"); 
}catch (Exception e)
{ e.printStackTrace();
}
IN WEB.XML
EmailTicket
com.cloudnowtech.EmailAgentServlet
EmailTicket
/_ah/mail/*
IN appengine-web-app
mail
HERE I'M SENDING THE CODE. PLEASE CORRECT IT – 
An important part of sending email is to, well, to send it. Perhaps you missed this part:
// Hand the message to the default transport service for delivery.
Transport.send(msg);
If you take a peek over on the right there ---->,
Wander the related questions for yourself and you should find some helpful tidbits.
Welcome to StackOverflow and have a nice day.
It looks like this:
I got answer. there is no setting for forward and reply email to receive. I declared field as String but reply or forward mail size as more than 500 character. so change as Text. now its working fine. thanks for all.
Thanks
Murugavel

Is there a way to change from address/email id on email sent from Google App engine Mail

Is there a way to change "from address" or email-id on email sent from Google App engine Code ? I am able to change the reply-to address but send-from mail address is only taking Administrator email id. Is there an application setting through which i can change the sent from email id ?
Message msg = new MimeMessage(session11);
msg.setFrom(new InternetAddress(Constants.DB.Connection.ADMINEMAIL, "TEST MAIL"));
msg.addRecipient(Message.RecipientType.TO, new InternetAddress(useremail, " TEST MAIL"));
msg.setReplyTo(new javax.mail.Address[]
{
new javax.mail.internet.InternetAddress(" testemail#xyz.com")
});
msg.setSubject(subject);
msg.setContent(message,"text/html");
Transport.send(msg);
Any suggestion or help would be appreciated
Yes, you can change the sender. But, that email must be listed as an administrator (developer). Your app can have more than one administrator.

Email verification through silverlight

I've built a Silverlight website where users can create an account and login. Right now, users just create an account through a form and can directly login. I want to incorporate a email verification feature, where the user will receive an email with a verification URL and only then can he login. I also wish to incorporate a forgot password feature that sends an email to the users registered email address to recover password.
How can I do this in silverlight. I'm using Windows SQL Azure as the back-end database. Will I have to create a separate Application for creating user accounts and recovering passwords?
Hope this helps you out on part A of your problem.
I noticed the post might throw you off a bit, so I decided to write a method that will do this for you in the quickest amount of time.
public bool Send(string fromEmail, string toEmail, string subject, string body)
{
try
{
MailMessage message = new MailMessage();
message.From = new MailAddress(fromEmail);
message.To.Add(new MailAddress(toEmail));
message.Subject = subject;
message.Body = body;
message.IsBodyHtml = false;
SmtpClient smtp = new SmtpClient();
smtp.EnableSsl = true;
smtp.Send(message);
return true;
}
catch (Exception ex)
{
return false;
}
}
Essentially, once they create their account you would want to call this filling out all variables. Make sure in your body of text you have a link that sends them to a page where they can submit "activate" their account.
This will essentially be a bit value in the database that is set to false by default and won't be set to true until they click on the "submit" or "activate" button from the link that would be in the body of text.
For password recovery you would do the same. Except instead of sending them to a page to activate their account you'd send them to a page where they could just re-create their password. Since the database doesn't care if the password is old or new you could just send them to a page where they create a new password. You wouldn't even need to create a temp password for them (Unless you wanted to for experience and for a extra caution).
Happy Coding! ;)

Resources