NO [UNAVAILABLE] FETCH Server error while fetching messages - jakarta-mail

Have anyone met this exception before? I cannot figure out what is the problem .
javax.mail.MessagingException: A415 NO [UNAVAILABLE] FETCH Server error while fetching messages;
nested exception is:
com.sun.mail.iap.CommandFailedException: A415 NO [UNAVAILABLE] FETCH Server error while fetching messages
at com.sun.mail.imap.IMAPMessage.loadEnvelope(IMAPMessage.java:1268)
at com.sun.mail.imap.IMAPMessage.getReceivedDate(IMAPMessage.java:393)
at eu.memshare.modules.mail.UserMail$3.match(UserMail.java:805)
at javax.mail.Message.match(Message.java:705)
at javax.mail.Folder.search(Folder.java:1270)
at com.sun.mail.imap.IMAPFolder.search(IMAPFolder.java:1918)
at javax.mail.Folder.search(Folder.java:1231)
at com.sun.mail.imap.IMAPFolder.search(IMAPFolder.java:1873)
at eu.memshare.modules.mail.UserMail.fetchMail(UserMail.java:823)
at eu.memshare.modules.mail.UserMail.run(UserMail.java:772)
Caused by: com.sun.mail.iap.CommandFailedException: A415 NO [UNAVAILABLE] FETCH Server error while fetching messages
at com.sun.mail.iap.Protocol.handleResult(Protocol.java:351)
at com.sun.mail.imap.IMAPMessage.loadEnvelope(IMAPMessage.java:1263)
... 9 more
This is the code where the exception is thrown:
SearchTerm term = new SearchTerm() {
#Override
public boolean match(Message message) {
try {
if(message.isExpunged()){
inbox.expunge();
return false;
}else if(message.getFlags().contains(Flags.Flag.DELETED)) {
return false;
}
long min = Math.min(System.currentTimeMillis(), lastQueryDate.getTime());
Date when = new Date(min);
Date receivedDate = message.getReceivedDate();
boolean after = when.before(receivedDate);
if (all) {
return true;
} else if (after) {
lastQueryDate = receivedDate;
return true;
}
} catch (MessagingException e) {
e.printStackTrace();
return false;
}
return false;
}
};

It's an error message from your server. You'll need to check your server log files or contact your server vendor or provider to find out what's wrong.

Related

Getting 400 from samltest.id when attempting SP-initiated worflow

I have used itfoxtec's SAML2 library to implement an SP in my ASP.NET MVC app. I am testing using samltest.id as the IdP. The IdP-initiated workflow works perfectly, but the SP-initiated workflow always gets a 400 error back from samltest.id. I have attempted to look through samltest.id's log to see if an error is being recorded there for my request, but I cannot seem to find anything there.
This is the Action that handles the URL that he user would go to when initiating SSO:
public ActionResult SSOLogin() {
LogManager logger = new LogManager("SSOLogin");
string hostname = this.GetHostname();
SchoolSettings settings = this.GetClientSettings();
if (settings.UseSAMLSSO) {
Saml2Configuration samlConfig = null;
try {
samlConfig = SamlConfigLoader.GetSaml2Config(HttpContext, settings, this.IsSandbox());
} catch (Exception e) {
logger.exception($"loading Saml2Configuration for {hostname}", e);
}
if (samlConfig != null) {
try {
var binding = new Saml2RedirectBinding();
binding.SetRelayStateQuery(new Dictionary<string, string> { { "Home/Index", Url.Content("~/") } });
return binding.Bind(new Saml2AuthnRequest(samlConfig) {
}).ToActionResult();
} catch (Exception e) {
logger.error($"Exception redirecting to IdP. {e.GetType().ToString()}: {e.Message}\n{e.StackTrace}");
ViewBag.ssoerror = $"Error redirecting to IdP for {hostname}";
}
} else {
logger.critical($"Could not load SAML2 configuration for {hostname}");
ViewBag.ssoerror = $"Could not load SAML2 configuration for {hostname}";
}
} else {
ViewBag.ssoerror = "SSO is not configured for this client. Please contact Support";
}
return Redirect("/Home/SSOError");
}
The method that loads a client-specific metadata looks like this:
public static Saml2Configuration GetSaml2Config(HttpContextBase context, SchoolSettings forSchool, bool forSandbox) {
LogManager log = new LogManager("getSaml2Config");
Saml2Configuration config = new Saml2Configuration();
if (!forSandbox) {
config.Issuer = _saml2Issuer;
} else {
config.Issuer = _saml2IssuerSandbox;
}
config.SignatureAlgorithm = _saml2SignatureAlgo;
config.CertificateValidationMode = X509CertificateValidationMode.None;
config.RevocationMode = (X509RevocationMode)Enum.Parse(typeof(X509RevocationMode), ConfigurationManager.AppSettings["Saml2:RevocationMode"]);
config.AllowedAudienceUris.Add(config.Issuer);
var entityDescriptor = new EntityDescriptor();
if (forSchool.SAMLMetadataLocationIsUrl) {
try {
entityDescriptor.ReadIdPSsoDescriptorFromUrl(new Uri(forSchool.SAMLMetadataLocation));
} catch (Exception e) {
log.error($"Exception caught loading metadata from school {forSchool.Hostname} at URL {forSchool.SAMLMetadataLocation}\n Exception {e.GetType().ToString()}: {e.Message}\n{e.StackTrace}");
entityDescriptor.IdPSsoDescriptor = null;
}
} else {
var schoolMetadataPath = context.Server.MapPath("~/App_Data/SAMLMetadata/" + forSchool.SAMLMetadataLocation);
log.info($"Loading metadata for school {forSchool.Hostname} from file {schoolMetadataPath}");
try {
entityDescriptor.ReadIdPSsoDescriptorFromFile(schoolMetadataPath);
} catch (IOException ioe) {
log.error($"IOException caught loading metadata for school {forSchool.Hostname} from file {schoolMetadataPath}: {ioe.Message}\n{ioe.StackTrace}");
entityDescriptor.IdPSsoDescriptor = null;
} catch (Exception e) {
log.error($"Exception caught loading metadata for school {forSchool.Hostname} from file {schoolMetadataPath}\n Exception {e.GetType().ToString()}: {e.Message}\n{e.StackTrace}");
entityDescriptor.IdPSsoDescriptor = null;
}
}
if (entityDescriptor.IdPSsoDescriptor != null) {
if (entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.Count() > 0) {
config.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.First().Location;
} else {
log.error($"WARNING: metadata for {forSchool.Hostname} does not have any SingleSignOnServices that could be parsed.");
}
if (entityDescriptor.IdPSsoDescriptor.SingleLogoutServices.Count() > 0) {
config.SingleLogoutDestination = entityDescriptor.IdPSsoDescriptor.SingleLogoutServices.First().Location;
} else {
log.error($"WARNING: metadata for {forSchool.Hostname} does not have any SingleLogoutServices that could be parsed.");
}
if (entityDescriptor.IdPSsoDescriptor.SigningCertificates.Count() > 0) {
config.SignatureValidationCertificates.AddRange(entityDescriptor.IdPSsoDescriptor.SigningCertificates);
} else {
log.error($"WARNING: metadata for {forSchool.Hostname} does not have any SigningCertificates that could be parsed.");
}
} else {
throw new Exception("IdPSsoDescriptor not loaded from metadata.");
}
return config;
}
If it would help to clarify the situation, I can add the code for the AssertionConsumerService Action which works perfectly in an IdP-initiated scenario.
I discovered the problem. It comes down to this line of code in the GetSaml2Config method:
config.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.First().Location;
This naively takes the first SingleSignOnService element in the metadata and decides that it is the correct one to use, but that was not always the case that this assumption was true. What I really wanted was to get a SingleSignOnService element for and HTTP-POST binding:
config.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.Where(s => s.Binding.ToString().IndexOf("HTTP-POST") > 0).FirstOrDefault()?.Location;
This works well for all of the cases that I have found since.
Your code looks correct.
It is probably an integration issue but very hard to find if the IdP do not log an error message.
What error status message do you get back instead of success, maybe that tells you something.
Maybe the IdP do not accept the SAML 2.0 Authn Response, here is something to look for:
The config.SingleSignOnDestination probably is required
Meybe the IdP requere the request to be signed
It is also possible to add other attributes in the request, do the IdP documentation describe any requirements?

JavaMail Check GMail INBOX is taking too long to connect and answer back

I have a process that must check the INBOX on GMail for a failure message, it's working except for the problem of the time it takes to connect and check the message, it takes about 1 minute, that is too much time.
My code:
public static SendResult sendingSuccess(final String email) {
SendResult result = new SendResult();
try {
Properties props = new Properties();
props.setProperty("mail.store.protocol", "imaps");
props.setProperty("mail.imap.com", "993");
props.setProperty("mail.imap.connectiontimeout", "5000");
props.setProperty("mail.imap.timeout", "5000");
Session session = Session.getDefaultInstance(props);
Store store = session.getStore("imaps");
store.connect("imap.googlemail.com", 993, GMAIL_USER, GMAIL_PASSWORD);
// Select and open folder
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);
// What to search for
SearchTerm searchTerm = new SearchTerm() {
private static final long serialVersionUID = -7187666524976851520L;
public boolean match(Message message) {
try {
String content = getContent(message);
boolean daemon = (message.getFrom()[0].toString()).contains("mailer-daemon#googlemail.com");
boolean failure = message.getSubject().contains("Failure");
boolean foundWarning = content.contains(email);
if (daemon && failure && foundWarning) {
return true;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
};
// Fetch unseen messages from inbox folder
Message[] messages = inbox.search(searchTerm);
// If there is no message then it's OK
result.setStatus(messages.length == 0);
result.setMessage(result.isStatus() ? "No failure message found for " + email : "Failure message found for " + email);
// Flag message as DELETED
for (Message message : messages) {
message.setFlag(Flags.Flag.DELETED, true);
}
// disconnect and close
inbox.close(false);
store.close();
} catch (Exception ex) {
result.setMessage(ex.getMessage());
ex.printStackTrace();
}
return result;
}
When I run this code to query the failure message it takes more than 1 minute to return the result to me.
======= Checking Gmail account for message failure! =====
Start...: 09:00:33
Finish..: 09:01:01
Result..: SendResult [status=true, message=No failure found for wrong.user#gmxexexex.net]
Is there any way to reduce this time?
The problem is most likely because you've written your own search term. JavaMail doesn't know how to translate your search term into an IMAP SEARCH request so it executes the search on the client, which requires downloading all the messages to the client to search there. Try this instead:
SearchTerm searchTerm = new AndTerm(new SearchTerm[] {
new FromStringTerm("mailer-daemon#googlemail.com"),
new SubjectTerm("Failure"),
new BodyTerm(email)
});
That will allow the search to be done by the IMAP server.

error handling in Akka Kafka Producer

I am using reactive-kafka-core 0.10.1 (targeting Kafka 0.9.x). It looks like Kafka producer actor is stopped whenever an error is encountered from the callback function. Is there any way to customize this behavior? Our use case is to try to recover and resend the messages.
private def processElement(element: ProducerMessage[K, V]) = {
val record = richProducer.props.partitionizer(element.value) match {
case Some(partitionId) => new ProducerRecord(richProducer.props.topic, partitionId, element.key, element.value)
case None => new ProducerRecord(richProducer.props.topic, element.key, element.value)
}
richProducer.producer.send(record, new Callback {
override def onCompletion(metadata: RecordMetadata, exception: Exception) = {
if (exception != null) {
handleError(exception)
}
}
})
()} private def handleError(ex: Throwable) = {
log.error(ex, "Stopping Kafka subscriber due to fatal error.")
stop()
}

Get Unread emails from Google API

I'm trying to get the count of unread email using google API, but not able. ANy help is highly appreciated. I'm not getting any error, but the count doesnt match the actual number shown in gmail.
try
{
String serviceAccountEmail = "xxx#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"C:\Projects\xxx\xyz\API Project-xxxxx.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
User = "xxx#gmail.com",
Scopes = new[] { Google.Apis.Gmail.v1.GmailService.Scope.GmailReadonly }
}.FromCertificate(certificate));
var gmailservice = new Google.Apis.Gmail.v1.GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "GoogleApi3",
});
try
{
List<Message> lst = ListMessages(gmailservice, "xxx#gmail.com", "IN:INBOX IS:UNREAD");
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
}
catch (Exception ex)
{
}
Just do: labels.get(id="INBOX") and it has those types of stats (how many messages in that label, how many are unread, and same for threads).
https://developers.google.com/gmail/api/v1/reference/users/labels/get
You can use the ListMessages method from the API example (included for completeness) for searching:
private static List<Message> ListMessages(GmailService service, String userId, String query)
{
List<Message> result = new List<Message>();
UsersResource.MessagesResource.ListRequest request = service.Users.Messages.List(userId);
request.Q = query;
do
{
try
{
ListMessagesResponse response = request.Execute();
result.AddRange(response.Messages);
request.PageToken = response.NextPageToken;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
} while (!String.IsNullOrEmpty(request.PageToken));
return result;
}
You can use this search method to find unread messages, for example like this:
List<Message> unreadMessageIDs = ListMessages(service, "me", "is:unread");
The q parameter (query) can be all kinds of stuff (it is the same as the gmail search bar on the top of the web interface), as documented here: https://support.google.com/mail/answer/7190?hl=en.
Note that you only a few parameters of the Message objects are set. If you want to retreive the messages you'll have to use GetMessage method from the api:
public static Message GetMessage(GmailService service, String userId, String messageId)
{
try
{
return service.Users.Messages.Get(userId, messageId).Execute();
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
return null;
}
I agree that the API is not straight forward and misses a lot of functionality.
Solution for .Net:
// Get UNREAD messages
public void getUnreadEmails(GmailService service)
{
UsersResource.MessagesResource.ListRequest Req_messages = service.Users.Messages.List("me");
// Filter by labels
Req_messages.LabelIds = new List<String>() { "INBOX", "UNREAD" };
// Get message list
IList<Message> messages = Req_messages.Execute().Messages;
if ((messages != null) && (messages.Count > 0))
{
foreach (Message List_msg in messages)
{
// Get message content
UsersResource.MessagesResource.GetRequest MsgReq = service.Users.Messages.Get("me", List_msg.Id);
Message msg = MsgReq.Execute();
Console.WriteLine(msg.Snippet);
Console.WriteLine("----------------------");
}
}
Console.Read();
}

How to make a correct select query on google endpoint?

I created an Android project using Google Cloud Endpoints, I created a model class Poll.java and now I want to make a query in the PollEndpoint.java class, to retrieve a poll with a specific author.
This is the query code in PollEndpoint.java
#ApiMethod(name = "getSpecificPoll", path="lastpoll")
public Poll getSpecificPoll(#Named("creator") String creator) {
EntityManager mgr = getEntityManager();
Poll specificPoll = null;
try {
Query query = mgr.createQuery("select from Poll where creator
='"+creator+"'");
specificPoll = (Poll) query.getSingleResult();
} finally {
mgr.close();
}
return specificPoll;
}
The code in the client part is:
private class PollQuery extends AsyncTask<Void, Void, Poll> {
#Override
protected Poll doInBackground(Void... params) {
Poll pollQuery = new Poll();
Pollendpoint.Builder builderQuery = new Pollendpoint.Builder(
AndroidHttp.newCompatibleTransport(), new
JacksonFactory(),null);
builderQuery = CloudEndpointUtils.updateBuilder(builderQuery);
Pollendpoint endpointQuery = builderQuery.build();
try {
pollQuery =
endpointQuery.getSpecificPoll("Bill").execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (pollQuery != null){
System.out.println(pollQuery.getKeyPoll().getId());
} else System.out.println("Null query");
return null;
}
The problem is that the server throw an exception:
javax.persistence.PersistenceException: FROM clause of query has class com.development.pollmeproject.Poll but no alias
at org.datanucleus.api.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:302)
I think that the query statement is not correct, how can I write a correct one?
The query you provided is NOT valid JPQL. JPQL is more of the form
SELECT p FROM Poll p WHERE p.creator = :creatorParam
The error message does tell you that though, so I'm not sure why you're not sure of it

Resources