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
Related
I am using the code from this tutorial with minimal modifications. Here is my code: `
public static void receiveEmail(String hst, String stype, String user, String password) {
try {
Properties props = new Properties();
props.put("mail.store.protocol", "pop3");
props.put("mail.pop3s.host", hst);
props.put("mail.pop3s.port", "995");
props.put("mail.pop3.starttls.enable", "true");
Session sess = Session.getDefaultInstance(props);
Store st = sess.getStore("pop3s");
st.connect(hst, user, password);
Folder emailFolder = st.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
Message[] messages = emailFolder.getMessages();
Message message = messages[229];
System.out.println("Welcome To Email");
System.out.println("Subject: " + message.getSubject());
System.out.println("From: " + message.getFrom()[0]);
String body = "body";
Multipart part = (Multipart) message.getContent();
MimeBodyPart mimePart = null;
for (int i = 0; i < part.getCount(); i++) {
mimePart = (MimeBodyPart) part.getBodyPart(i);
System.out.println(mimePart.getContent());
System.out.println("========");
}
emailFolder.close(false);
st.close();
}// catch (NoSuchProviderException e) {e.printStackTrace();}
catch (MessagingException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
}
`
I am calling receive email from a driver class. This is literally the only method being called.
I will run the code and it will work fine, printing the contents of the 229th email. Then, if i run it again, with not changes whatsoever, I get an array index out of bounds exception saying index 229 is out of bounds for length 229. As I understand it, when i run it, the code works fine, but somehow the email I want to access is no longer accessible. I have been trying to access the last email for testing purposes and I knew which number it is. What I think is happening is that the code is making the email I just accessed unavailable. I just added a print line and confirmed that when i first run it, the length is such that the message being accessed is the last element in the array, upon running the program again, the array is mysteriously one element smaller. I have verified that the emails are actually not disappearing from my account. I think i started at email 250 or something and have been gradually losing access. Another interesting thing to note is that yesterday, I was working with a different email account that only had 19 emails in it, after a short period of time, I was suddenly unable to list out the emails in that account with code. The emails were there, I could send emails with code, but not access the emails stored on that account.
I want to know what is the best way(load quickly the messages from the server) to get messages from one mailbox(e.g: INBOX, OUTBOX). I've found the folder feth() method and getMessages() method but I don't understand what is better between the two methods.
My current code use getMessages() method but it's still slow:
public static void fetch(String Host, String storeType, String user,
String password) {
try {
// create properties field
Properties properties = new Properties();
properties.put("mail.store.protocol", "imaps");
properties.put("mail.imaps.host", Host);
properties.put("mail.imaps.port", "993");
properties.put("mail.imaps.starttls.enable", "true");
Session emailSession = Session.getDefaultInstance(properties);
// emailSession.setDebug(true);
// create the IMAP store object and connect with the imap server
Store store = emailSession.getStore("imaps");
store.connect(Host, user, password);
// create the folder object and open it
Folder emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
// retrieve the messages from the folder in an array and print it
Message[] messages = emailFolder.getMessages();
System.out.println("messages.length---" + messages.length);
for (int i = 0; i < messages.length; i++) {
Message message = messages[i];
System.out.println("---------------------------------");
writePart(message);
String line = reader.readLine();
if ("YES".equals(line)) {
message.writeTo(System.out);
} else if ("QUIT".equals(line)) {
break;
}
}
// close the store and folder objects
emailFolder.close(false);
store.close();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
Can someone explain me what's the right and the better way!
The fetch method is use to prefetch message data in bulk. Normally it's used to fetch and cache message metadata, headers, etc. This is useful if you only need to examine a small amount of message metadata to determine whether to process a message.
You can also use the fetch method to fetch and cache the entire content of a message. Unless you are accessing all the content of every message, you don't want to fetch the entire message using the fetch method. When used that way it behaves more like the POP3 protocol except that it fetches multiple messages at once. Obviously caching entire messages can use a lot of memory.
The getMessages method fetches no message data at all. All it does is give you a "handle" through which you can access message data, which will be fetched on demand. If you call the getSubject method, it will fetch the Subject (which is part of the "envelope" metadata). You might want to use the fetch method to prefetch and cache this envelope data to make subsequent operations more efficient. And when you decide you need to read the body or attachments of a message, that data will be fetched at that point.
Perhaps the fetch method should've been named prefetchAndCache. :-)
I want to send mail with accented characters from spanish and french.I am able to send with the below code
SimpleMailMessage message = new SimpleMailMessage(simpleMailMessage);
message.setTo(emailAddress);
message.setText(bodyContent);
message.setSubject(subject);
message.setFrom(fromMail);
try {
mailSender.send(message);
} catch (MailException e) {
e.printStackTrace();
}
But when i try to send mail with accented characters (nÄrendra_pandeyñõ#abc.com) in FROM and TO field it gives following error
javax.mail.internet.AddressException: Local address contains control or >whitespace in string ``närendra_pandeyñõ#abc.com''
Use the InternetAddress contructor that takes separate personal name and email address parameters.
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 am trying to access my gmail account and retrieve the information of all unread emails from that.
I have written my code after referring many links. I am giving a few links for reference.
Send & Receive emails through a GMail account using Java
Java Code to Receive Mail using JavaMailAPI
To test my code, I created one Gmail account. So I received 4 messages in that from Gmail.
I run my application after checking number of mails. That showed correct result. 4 unread mails.
All the infomation was being displayed (e.g. date, sender, content, subject, etc.)
Then I logged in to my new account, read one of the emails and rerun my application.
Now the count of unread message should have been 3, but it displays "No. of Unread Messages : 0"
I am copying the code here.
public class MailReader
{
Folder inbox;
// Constructor of the calss.
public MailReader() {
System.out.println("Inside MailReader()...");
final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
/* Set the mail properties */
Properties props = System.getProperties();
// Set manual Properties
props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.pop3.socketFactory.fallback", "false");
props.setProperty("mail.pop3.port", "995");
props.setProperty("mail.pop3.socketFactory.port", "995");
props.put("mail.pop3.host", "pop.gmail.com");
try
{
/* Create the session and get the store for read the mail. */
Session session = Session.getDefaultInstance(
System.getProperties(), null);
Store store = session.getStore("pop3");
store.connect("pop.gmail.com", 995, "abc#gmail.com",
"paasword");
/* Mention the folder name which you want to read. */
// inbox = store.getDefaultFolder();
// inbox = inbox.getFolder("INBOX");
inbox = store.getFolder("INBOX");
/* Open the inbox using store. */
inbox.open(Folder.READ_ONLY);
/* Get the messages which is unread in the Inbox */
Message messages[] = inbox.search(new FlagTerm(new Flags(
Flags.Flag.SEEN), false));
System.out.println("No. of Unread Messages : " + messages.length);
/* Use a suitable FetchProfile */
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add(FetchProfile.Item.CONTENT_INFO);
inbox.fetch(messages, fp);
try
{
printAllMessages(messages);
inbox.close(true);
store.close();
}
catch (Exception ex)
{
System.out.println("Exception arise at the time of read mail");
ex.printStackTrace();
}
}
catch (MessagingException e)
{
System.out.println("Exception while connecting to server: "
+ e.getLocalizedMessage());
e.printStackTrace();
System.exit(2);
}
}
public void printAllMessages(Message[] msgs) throws Exception
{
for (int i = 0; i < msgs.length; i++)
{
System.out.println("MESSAGE #" + (i + 1) + ":");
printEnvelope(msgs[i]);
}
}
public void printEnvelope(Message message) throws Exception
{
Address[] a;
// FROM
if ((a = message.getFrom()) != null) {
for (int j = 0; j < a.length; j++) {
System.out.println("FROM: " + a[j].toString());
}
}
// TO
if ((a = message.getRecipients(Message.RecipientType.TO)) != null) {
for (int j = 0; j < a.length; j++) {
System.out.println("TO: " + a[j].toString());
}
}
String subject = message.getSubject();
Date receivedDate = message.getReceivedDate();
Date sentDate = message.getSentDate(); // receivedDate is returning
// null. So used getSentDate()
String content = message.getContent().toString();
System.out.println("Subject : " + subject);
if (receivedDate != null) {
System.out.println("Received Date : " + receivedDate.toString());
}
System.out.println("Sent Date : " + sentDate.toString());
System.out.println("Content : " + content);
getContent(message);
}
public void getContent(Message msg)
{
try {
String contentType = msg.getContentType();
System.out.println("Content Type : " + contentType);
Multipart mp = (Multipart) msg.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++) {
dumpPart(mp.getBodyPart(i));
}
} catch (Exception ex) {
System.out.println("Exception arise at get Content");
ex.printStackTrace();
}
}
public void dumpPart(Part p) throws Exception {
// Dump input stream ..
InputStream is = p.getInputStream();
// If "is" is not already buffered, wrap a BufferedInputStream
// around it.
if (!(is instanceof BufferedInputStream)) {
is = new BufferedInputStream(is);
}
int c;
System.out.println("Message : ");
while ((c = is.read()) != -1) {
System.out.write(c);
}
}
public static void main(String args[]) {
new MailReader();
}
}
I searched on google, but I found that you should use Flags.Flag.SEEN to read unread emails.
But thats not showing correct results in my case.
Can someone point out where I might be doing some mistake?
If you need whole code, I can edit my post.
Note: I edited my question to include whole code instead of snippet I had posted earlier.
Your code should work. You can also use the Folder.getUnreadMessageCount() method if all you want is the count.
JavaMail can only tell you what Gmail tells it. Perhaps Gmail thinks that all those messages have been read? Perhaps the Gmail web interface is marking those messages read? Perhaps you have another application monitoring the folder for new messages?
Try reading an unread message with JavaMail and see if the count changes.
You might find it useful to turn on session debugging so you can see the actual IMAP responses that Gmail is returning; see the JavaMail FAQ.
You cannot fetch unread messages with POP3. From JavaMail API:
POP3 supports no permanent flags (see Folder.getPermanentFlags()). In
particular, the Flags.Flag.RECENT flag will never be set for POP3
messages. It's up to the application to determine which messages in a
POP3 mailbox are "new".
You can use IMAP protocol and use the SEEN flag like this:
public Message[] fetchMessages(String host, String user, String password, boolean read) {
Properties properties = new Properties();
properties.put("mail.store.protocol", "imaps");
Session emailSession = Session.getDefaultInstance(properties);
Store store = emailSession.getStore();
store.connect(host, user, password);
Folder emailFolder = store.getFolder("INBOX");
// use READ_ONLY if you don't wish the messages
// to be marked as read after retrieving its content
emailFolder.open(Folder.READ_WRITE);
// search for all "unseen" messages
Flags seen = new Flags(Flags.Flag.SEEN);
FlagTerm unseenFlagTerm = new FlagTerm(seen, read);
return emailFolder.search(unseenFlagTerm);
}
Another thing to notice is that POP3 doesn't handle folders. IMAP gets folders, POP3 only gets the Inbox. More info at: How to retrieve gmail sub-folders/labels using POP3?
Change inbox.open(Folder.READ_ONLY); to inbox.open(Folder.READ_WRITE);
It will change your mail as read in inbox.
Flags seen = new Flags(Flags.Flag.RECENT);
FlagTerm unseenFlagTerm = new FlagTerm(seen, false);
messages = inbox.search(unseenFlagTerm);
The correct flag to use is
Flags.Flag.RECENT
please use this method to get the unread mails
getNewMessageCount()
refer below link:
https://javamail.java.net/nonav/docs/api/com/sun/mail/imap/IMAPFolder.html