In Javamail for EWS store, FlagTerm to check for unread mails in outlook mailbox is not giving correct results - jakarta-mail

I am trying to connect to my outlook mailbox using Javamail for EWS and fetch the details of unread emails from my outlook mailbox. It is connecting to the mailbox and giving total mails count correctly. I have used flagterm to check for unseen emails and did folder search with this flag. But the count of my unseen messages is always returned 0 despite of unseen mails existing in mailbox. Please find my code snippet below:
Properties properties = new Properties()
properties.setProperty("org.sourceforge.net.javamail4ews.util.Util.EnableServiceTrace", "true");
Session session = Session.getInstance(properties);
session.setDebug(true);
Store store = session.getStore("ewsstore");
store.connect(
"https://outlook.office365.com/EWS/Exchange.asmx",
"xyz#hotmail.com",
"Password");
Folder folder = store.getDefaultFolder();
folder.open(Folder.READ_ONLY);
Flags seen = new Flags(Flags.Flag.SEEN);
FlagTerm unseenFlagTerm = new FlagTerm(seen, false); //When flag set true,its giving total count
Message[] messagesunread = folder.search(unseenFlagTerm);
System.out.println(messagesunread.length);

Related

Send Email to a list of 200 records via Apex in Salesforce

I am executing the below code in an Apex Batch
The Query returns a list of 200 records and stores it in scope.
My Code is getting executed successfully, even after checking debug logs, there are no exceptions or any error. But the problem here is mails are getting delivered to only first few records in the list and none of the others are receiving the mails.
I went to workbench and checked the mail limits and they are decreasing from 1000 to 800. But only few ppl are getting the mails and others aren't. Below is the sample code.
List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
for(Service_Resource__c sr : (List<Service_Resource__c>)scope) {
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
if(owa.size()>0){
email.setOrgWideEmailAddressId(owa[0].Id);
}
else{
email.setSenderDisplayName('NoReply-ActNow');
}
email.setSubject(htmlsubject1NonSFUsers);
email.setToAddresses(new String[] {sr.Email__c});
email.setSaveAsActivity(false);
email.setHtmlBody(htmlbody1NonSFUsers);
email.setTemplateId(nonSFUsersEmailTemplate.Id);
mails.add(email);
}
if(mails.size()>0){
Messaging.sendEmail(mails);
}
Requesting you to help me out here to find out why the emails are not getting delivered to everyone even though the email limits are not over.
Thank you

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)

Read all emails from inbox after a specified date and time in java using javax.mail

Right now I am able to read all Unread emails messages using java but I need to read all emails after a specified date and time using JAVAX.Mail (ie javax.mail.jar), Please help me in retrieving all the emails using java after specified date and time (say 12 july 2013,1pm).
My code for reading mails :
Properties prop = System.getProperties();
prop.getProperty("mail.store.protocol", "imaps");
Session session = Session.getDefaultInstance(prop, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", "myGmailId#gmail.com", "mypassword");
inbox = store.getFolder("Inbox");
Here is one example taken from javax.mail.Message trying to fetch messages for a given date range
cal.add(Calendar.DAY_OF_MONTH, -1);
// We would get the bounce mails received yesterday
ReceivedDateTerm term = new ReceivedDateTerm(ComparisonTerm.EQ,newDate(cal.getTimeInMillis()));
Message[] messages = folder.search(term)
Another approach of using term could be:
SearchTerm olderThan = new ReceivedDateTerm(ComparisonTerm.LT, someFutureDate);
SearchTerm newerThan = new ReceivedDateTerm(ComparisonTerm.GT, somePastDate);
SearchTerm andTerm = new AndTerm(olderThan, newerThan);
inbox.search(andTerm);

Using DispositionNotification with Javamail

I am working with a set of specialized email servers that are configured to return Message Disposition Notifications (MDNs) upon successful receipt of the message. I have developed a Javamail client that is used to send messages to one of these servers and retrieve returned MDNs from the user's POP3 INBOX folder.
How do I go about getting at the disposition notification body part from the returned MimeMessage I retrieve from the user's inbox? I've found the com.sun.mail.dsn.DispositionNotification class but haven't seen an example of how to correctly create an instance of a DispositionNotification using the constructor:
DispositionNotification(InputStream)
Should I be able get the InputStream from a MimeMessage and use it to create the DispositionNotification, like so?
Message[] msgs = getInboxMessages();
DispositionNotification dn = new DispositionNotification(msgs[0].getInputStream();
Or is there some other way this should be done?
The getContent method on such a message should return a MultipartReport object (a special subclass of the usual MimeMultipart object), from which you can access the parts of the report. The MultipartReport.getReport() method will return either a DeliveryStatus or DispositionNotification object, depending on the type of the report.

Resources