In catch block of sending mail with Javamail API I'm using instanceof to categorize exceptions AuthenticationFailedException is doing its job But SendFailedException is not. I'm testing my application with some mail addresses that include some valid and some invalid addresses But SendFailedException do not trigger on invalid addresses.
Here is how I'm using catch block
catch (MessagingException ex) {
if (ex instanceof AuthenticationFailedException) {
JOptionPane.showMessageDialog(null, "Exception: \n" + "Athentication failed due to invalid sender mail or password\n");
} else if (ex instanceof SendFailedException) {
SendFailedException e = (SendFailedException) ex;
final Address[] invalidAddresses = e.getInvalidAddresses();
setFailedAddresses(invalidAddresses);
final Address[] validSentAddresses = e.getValidSentAddresses();
setConfirmedAddresses(validSentAddresses);
final Address[] validUnsentAddresses = e.getValidUnsentAddresses();
resend(validUnsentAddresses);
JOptionPane.showMessageDialog(null, "Exception: \n: " + "invalid mail address = "+invalidAddresses.length+"\nvalid addrs = "+validSentAddresses.length+"\nvalid not treated = "+validUnsentAddresses.length);
} else if (ex instanceof NoSuchProviderException) {
JOptionPane.showMessageDialog(null, "Exception: \n " + "No provider found with the name you specified");
Can you point out what where I'm wrong?
My application runs fine and send mails to valid addresses But exception not arise on invalid addresses.
Actually program do not enter into this exception.
Here is how I add Recipients
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(addrsString));
Where: addrsString is a string containing comma separated mail.
What I want is it should add invalid addresses to an array an shown in exception code that it is not doing right now.
Related
I have been using Javamail (version 1.6.4) for a while now, mostly for event listening, mail parsing and copy/delete mails (from Exchnage using IMAPS). Lately i was asked to use sub-folders for a business usecase. When moving mail from the Inbox folder to a sub-folder the UID changes so i'm using folder.search() in order to find the new UID. This works most of the times but sometimes the search goes indefnitley (or its duration is very long) which may lag the entire application.
Is there a way to set a timeout (or other way to throw an exception if it runs too long) for folder.search()?
I understood that imap search is done on the server side but i just wanted to validate. this is an example of how i send search to the server (we can assume subject is unique for this discussion):
private static String findMailIdBySubject(String mailbox, String srcFolder, String subject) {
Folder srcFolderObj = null;
boolean wasConnectionEstablished = connectToMail(mailbox);
if (!wasConnectionEstablished) {
return null;
}
// get mailboxStore object
MailboxStore mailboxStore = MailBoxStoreList.getMailStoreByMailBox(mailbox);
try {
// Open inbox folder to get messages metadata
srcFolderObj = mailboxStore.getStore().getFolder(srcFolder);
srcFolderObj.open(Folder.READ_WRITE);
// create search Term
SearchTerm term = new SearchTerm() {
private static final long serialVersionUID = 7L;
#Override
public boolean match(Message message) {
try {
String mailSubject = message.getSubject();
if (mailSubject == null) {
mailSubject = "";
}
if (mailSubject.equals(subject)) {
return true;
}
} catch (MessagingException ex) {
log.error("Failed to search for mail with mailbox: " + mailbox + " in folder: " + srcFolder
+ " subject: " + subject + " Error: " + ExceptionUtils.getStackTrace(ex));
}
return false;
}
};
// search for the relevant message
Message[] messages = srcFolderObj.search(term);
UIDFolder uf = (UIDFolder) srcFolderObj;
return String.valueOf(uf.getUID(messages[0]));
} catch (Exception e) {
log.error("Subject: Failed to find id of mail in mailbox " + mailbox + " in folder " + srcFolder
+ " , Error: " + ExceptionUtils.getStackTrace(e));
return null;
} finally {
try {
if (srcFolderObj != null && srcFolderObj.isOpen()) {
srcFolderObj.close();
}
} catch (Exception e) {
}
}
}
i also tried to replace SearchTerm override with the following but performance was the same:
SearchTerm searchTerm = new SubjectTerm(subject);
Thanks in advance!
I have a mapping in Informatica BDM that sends emails based on credentials stored in an SQL table (subject, body, recipients, sender, etc.). Previously my source was a Hive table and my code worked as intended but now with the SQL source table not all records are sent through. Running the data viewer shows that the relevant data is where it's supposed to be in the mapping at run-time. Initially I thought the troubles were with the records containing no CC field but have recently discovered if I go back and delete the CC recipients field of records that are accepted then those emails are sent through
//place our recipients into an array
String[] to_arr;
to_arr = recipients.split(";");//split on semi-colon in case there's more than one recipient
//place our CC'd recipients
String[] copy_arr;
copy_arr = copy_recipients.split(";");//split on the semi-colon character
// Include our host smtp server
String host = "my.server.ip.address";
Properties properties = System.getProperties();
properties.setProperty("mail.smtp.host", host);
// Get the default Session object.
Session session = Session.getDefaultInstance(properties);
try{
o_status ="MimeMessage not created";
MimeMessage message = new MimeMessage(session);
o_status ="FROM not set";
message.setFrom(new InternetAddress(from_address));
o_status = "TO not set";
//add our recipients
for(String receiver : to_arr)
message.addRecipient(Message.RecipientType.TO, new InternetAddress(receiver));
//add our CC'd recipients but make sure they exist first
o_status="failed to add CC'd recipients";
if(!isNullOrEmpty(copy_recipients))
for (String rec : copy_arr)
message.addRecipient(Message.RecipientType.CC, new InternetAddress(rec));
o_status ="Failed to set the subject line.";
message.setSubject(subject);
o_status ="Failed to set the body of the email.";
message.setContent(body, "text/html");
//transmit the message
try{
Transport.send(message);
o_status = "sent";
}
catch(SendFailedException e){
o_status= e;
}
catch(MessagingException e){
o_status = e;
}
catch(Exception e){
o_status = e;
}
}
//incase the message can't be sent
catch (MessagingException mex) {
System.out.println("Failed to send message....");
mex.printStackTrace();
}
Here's the implementation of isNullOrEmpty:
//checks if a string is empty or null
public static boolean isNullOrEmpty(String str) {
if(str != null && !str.isEmpty())
return false;
return true;
}
Any insight as to why an SQL table would behave differently than a Hive table in this given circumstance is much appreciated.
EDIT: I forgot to mention that the mapping runs without any errors in the log file, making it difficult to debug as informatica bdm doesn't really have a strong Java debugger to begin with.
Here's a sample of my data
I updated my code:
1) I added the following properties:
Properties props=new Properties();
props.put(smtp,host);
props.put("mail.smtp.reportsuccess","true");
props.put("mail.smtp.sendpartial", "true");
Then written this block as directed in answer:
}catch (MessagingException mex){
Exception ex = mex;
do {
if(ex instanceof SendFailedException) {
SendFailedException sfe = (SendFailedException) ex;
Address[] vsa = sfe.getValidSentAddresses();
Address[] vua = sfe.getValidUnsentAddresses();
Address[] ia = sfe.getInvalidAddresses();
if(vsa !=null || vsa.length>0){
String validSentAddresses = vsa[0].toString();
printReport("GSWvalidSentAddresses.txt", validSentAddresses);
}
else if(vua !=null || vua.length>0){
String validUnsentAddresses = vua[0].toString();
printReport("GSWvalidUnsentAddresses.txt", validUnsentAddresses);
}
else if(ia !=null || ia.length>0){
String invalidAddresses = ia[0].toString();
printReport("GSWinvalidAddresses.txt", invalidAddresses);
}
else{}
if (ex instanceof MessagingException)
ex = ((MessagingException) ex).getNextException();
else
ex = null;
}//
} while (ex != null);
}//main catch block
}
when it ran throws 504 Gateway Time-out--------nginx
Please advise
Thanks in anticipation
Set the mail.smtp.reportsuccess session property to true. This will cause Transport.send to always throw SendFailedException. Per the documentation:
When sending a message, detailed information on each address that fails is available in an SMTPAddressFailedException chained off the top level SendFailedException that is thrown. In addition, if the mail.smtp.reportsuccess property is set, an SMTPAddressSucceededException will be included in the list for each address that is successful. Note that this will cause a top level SendFailedException to be thrown even though the send was successful.
The use of the word 'chained' means you have to call MessagingException.getNextException().
Also of interest is to you is the 'mail.smtp.sendpartial' property which is also covered in the documentation.
You should also change the code to use Session.getInstance.
I'm working on an mailing app. The app can receive multiple recipient addresses. Once the "Send" button is pressed, a single message is sent containing multiple recipient addresses. Of course, by having this kind of system, there would be an SendFailedException if at least one of the addresses is invalid. Naturally, I would catch this and exception and try to work around with it. Here's my code so far:
catch (SendFailedException e)
{ try
{
System.out.println(e.getValidUnsentAddresses()!=null);
if (e.getValidUnsentAddresses()!=null) //with valid unsent addresses
{
String invalid = new String();
String valid = new String();
for (int i=0; i<e.getInvalidAddresses().length; i++)
{
invalid = invalid + e.getInvalidAddresses()[i].toString();
if (i+1<e.getInvalidAddresses().length)
{
invalid = invalid + ", ";
}
}
for (int i=0; i<e.getValidUnsentAddresses().length; i++)
{
valid = valid + e.getValidUnsentAddresses()[i].toString();
if (i+1<e.getValidUnsentAddresses().length)
{
valid = valid + ", ";
}
}
int choice = JOptionPane.showOptionDialog(null, invalid + " are invalid addresses. Send mail to valid addresses?", "Information", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, "No");
if (choice==0)
{
transport.sendMessage(message, e.getValidUnsentAddresses());
JOptionPane.showMessageDialog(null, "Sent message to " + valid + ".", "Information", JOptionPane.INFORMATION_MESSAGE);
}
}
else //no valid unsent addresses
{
JOptionPane.showMessageDialog(null, "All email addresses are invalid.", "Information", JOptionPane.ERROR_MESSAGE);
}
}
catch(MessagingException e2)
{ e2.printStackTrace(); }
}
Loop to add recipient addresses to message:
for (int i=0; i<listModel.getSize(); i++) //listModel is of DefaultListModel Class
{
message.addRecipient(Message.RecipientType.TO, new InternetAddress((String)listModel.getElementAt(i)));
}
Then at the end:
properties = System.getProperties();
session = Session.getDefaultInstance(properties);
transport = session.getTransport("smtp");
transport.connect(host, textEmail.getText(), new String(pwdPassword.getPassword()));
transport.sendMessage(message, message.getAllRecipients()); // <----this part throws the SendFailedException
transport.close();
Now onto the problem. You could see that there's an if-else statement immediately inside the catch block. I wanted to check whether there were any valid unsent addresses in the recipients. This way I can know if there are only invalid addresses in the recipients (as there are no valid sent addresses since the message fails to send because of the exception).
I've run some tests on the system. It works fine if all addresses are valid, however, when a single invalid address is included, a minor problem appears. If I were to put only invalid addresses in the recipients, it is supposed to go to the "else" part, but instead it always ends up in the "if" part of the statement.
While it is only a minor problem (it's only about prompts), I would still like to know why my condition doesn't work. I might be missing something about the SendFailedException
Try putting all invalid addresses and it should work
If is executed everytime because even if one valid address is there
e.getValidUnsentAddresses();
will not return null
I'm trying to send a lot of sms texts all at once, it works fine when i pull the numbers from the contacts themselves, but when i get them from the group i get an IllegalArgumentException that says "invalid destination address: trailing characters:" followed by the recipient's number.
I get the numbers from the contacts like this:
private void addContactGroup(BlackBerryContactGroup group) {
BlackBerryContact contact;
for(int i=0;i<group.numContacts();i++) {
_cntctsNmbrs.addElement(group.getAddress(i).trim());
}
}
And then i send the message:
try {
_conn = (MessageConnection)Connector.open("sms://");
final TextMessage msgOut = (TextMessage)
_conn.newMessage(MessageConnection.TEXT_MESSAGE,
"sms://"+_cntctsNmbrs.elementAt(i)+":0");
msgOut.setPayloadText(frmtdMsg);
_conn.send(msgOut);
} catch (final Exception e) {}
I searched all over but couldn't find this error anywhere.
it turns out that some of the rim oses add invisible control characters to the strings of group's addresses, i just called stringbuf.deleteCharAt(0) for each address and it worked out