Send email through Yahoo mail or Gmail with Java
I have a java email program that can take a mail host name , port number and then send an email, but I don't want to use the mail host at work, I wonder if I can send email through my Yahoo Mail or Gmail account with Java, do they have any Java API that my program can log me in and send emails ? Any sample code available ? Thanks.
Frank
[352 byte] By [
Ni_Mina] at [2007-11-27 4:00:20]

# 1
Have you read the JavaMail FAQ? Search for "Yahoo" and "Gmail".
# 2
Thanks for reminding me, I did some search on "Yahoo" and "Gmail". For Yahoo someone posted some code that didn't work, for gmail, there seems to be a solution for sending email from command line. I wonder if I can send full fledged email : with CC, BCC, Attachment, Html email with images inside ...
I've done it with a local mail host, but how to do it with Yahoo or Gmail ?
Frank
>Have you read the JavaMail FAQ? Search for "Yahoo" and "Gmail".
# 3
> I wonder if I can send full fledged email : with CC, BCC, Attachment, Html email with images inside
The answer to this is: Every SMTP server in the world supports this. Your code should not depend on what server you are connecting to, except the part that actually does the connection.
The JavaMail FAQ has specific entries related to problems you may encounter with Yahoo and Gmail.
# 4
Well, in the FAQ (as I looked at six months ago), it doesn't have an concrete sample code of how to connect to Yahoo or Gmail, it points to MrPostman, and I found that it's few years old, the latest update was (08/27/2005), I wonder if it can still connect to the latest versions of Yahoo or Gmail. I remember I downloaded it a few months ago, and couldn't figure out how to send emails with it from a java program.
Is there any sample code showing how to do it ?
Frank
# 5
Amazingly, I actually do update the FAQ from time to time. :-)It's not an issue of code, it's an issue of configuration. http://java.sun.com/products/javamail/FAQ.html#yahoomail
# 6
Hi , thanks for replying, I have noticed that question in the FAQ, but I don't have the Yahoo! Mail Plus, only the free account, and I have no plans to pay for the Yahoo! Mail Plus, does that mean there is no way out ?Frank
# 8
I do have Gmail, but how to send email via my java program ? Any sample code ?Frank> Switch to gmail?
# 9
Gee, I wonder if that information would be in the FAQ?Why don't you check and let me know...
# 10
Woo, like magic, how come I didn't see it before ?! Was it there ? But thank you for reminding me ! ^_^
I've downloaded them (both activation.jar & mail.jar, I had the older versions), and will look into it, thanks again !
Frank
> Gee, I wonder if that information would be in the FAQ?
# 11
Does the Gmail approach applies to other web based emails ? I have an account with IX Hosting and have email accounts there that I can access from the web, can I use JavaMail to communicate with it ? In other words, is the Gmail approach a standard way of doing things with JavaMail that can by carried over to others ?
# 12
There is a standard way in JavaMail to configure access to SMTP,
IMAP, and POP3 servers. Not all web mail providers provide direct
access to their servers using those protocols. For example,
Hotmail does not. You'll need to check with your service provider.
If they provide instructions on how to configure other email clients
such as Thunderbird, you can probably configure JavaMail to access
the server.
# 13
Great news ! I did setup Thunderbird to get emails from my accounts there, and it sounds like I'll be able to talk to my web mail accounts there from JavaMal, thanks, I'll give it a try.Frank
# 14
There is some news about Yahoo Mail API below, I wonder if the new release will work with JavaMail ? http://www.profy.com/2007/03/30/yahoo-mail-api-released http://www.readwriteweb.com/archives/yahoo_mail_api.phpFrank
# 15
In the FAQ, it says "A bug in older versions of the smtpsend command causes it to set the incorrect properties when using the -S (SSL) option, so we work around that bug by ..."
Does that mean in this new version of smtpsend, the bug has been fixed and therefore we can simply do the following ?
java smtpsend -S -M smtp.gmail.com -U user -P passwd -A user@gmail.com
Frank
# 16
I have several options as to use which host, either local or from several different web accounts, I wonder if there is a simply way to check which ones are available without actually sending a email to see if it succeeded or failed to find out ?Frank
# 17
> There is some news about Yahoo Mail API below, I
> wonder if the new release will work with JavaMail ?
It doesn't appear that they've written a JavaMail provider
to access Yahoo Mail using their new web service, and I
can't tell from their terms of use whether doing that would
be allowed.
# 18
> I have several options as to use which host, either
> local or from several different web accounts, I
> wonder if there is a simply way to check which ones
> are available without actually sending a email to see
> if it succeeded or failed to find out ?
You can connect to the server, possibly authenticating,
and see if that works. Success connecting doesn't
guarantee that you'll be able to send mail, but it's a good
indicator.
# 19
> In the FAQ, it says "A bug in older versions
> of the smtpsend command causes it to set the
> incorrect properties when using the -S (SSL) option,
> so we work around that bug by ..."
>
> Does that mean in this new version of
> smtpsend, the bug has been fixed and therefore we can
> simply do the following ?
>
> java smtpsend -S -M smtp.gmail.com -U user -P passwd
> -A user@gmail.com
Yes, that should work. Did you try it?
# 20
Yes, I tried and it worked. Thanks.Frank
# 21
Does anyone know why Gmail has the following error message :Technical details of permanent failure:PERM_FAILURE: Message rejected for Sector 5 policy reasonsFrank
# 22
> Does anyone know why Gmail has the following error
> message :
>
> Technical details of permanent failure:
> PERM_FAILURE: Message rejected for Sector 5 policy
> reasons
No, but a quick google search shows that you're not alone.
If you figure it out, please post the answer here.
# 23
Missing the "To:" field value will probably cause this error.Frank
# 24
I am accessing my ISP's mail host at work with JavaMail and got the following error, my actual valid email address is replaced below by
[ my_email@address.com ] :
===========================================================
To: my_email@address.com
Subject: Hello Frank
DEBUG: setDebug: JavaMail version 1.4ea
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "mail.nmjava.com", port 25, isSSL false
220 mail54.opentransfer.com ESMTP
DEBUG SMTP: connected to host "mail.nmjava.com", port: 25
EHLO IT-FC-D-FNI
250-mail54.opentransfer.com
250-PIPELINING
250-8BITMIME
250 SIZE 1048576000
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "SIZE", arg "1048576000"
DEBUG SMTP: use8bit false
MAIL FROM:<fni@IT-FC-D-FNI>
250 ok
RCPT TO:<my_email@address.com>
553 sorry, that domain isn't allowed to be relayed thru this MTA (#5.7.1)
DEBUG SMTP: Invalid Addresses
DEBUG SMTP:my_email@address.com
DEBUG SMTP: Sending failed because of invalid destination addresses
RSET
DEBUG SMTP: EOF: [EOF]
QUIT
DEBUG SMTP: EOF: [EOF]
javax.mail.SendFailedException: Invalid Addresses;
nested exception is:
com.sun.mail.smtp.SMTPAddressFailedException: 553 sorry, that domain isn't allowed to be relayed thru this MTA (#5.7.1)
at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:1196)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:584)
at smtpsend.main(smtpsend.java:150)
Caused by: com.sun.mail.smtp.SMTPAddressFailedException: 553 sorry, that domain isn't allowed to be relayed thru this MTA (#5.7.1)
at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:1047)
... 2 more
ADDRESS FAILED:
Address: my_email@address.com
Command: RCPT TO:<my_email@address.com>
RetCode: 553
Response: 553 sorry, that domain isn't allowed to be relayed thru this MTA (#5.7.1)
===========================================================
Does anyone know why ?
Frank
# 25
Back to the FAQ again, where a search for the word "relay" will explain.
# 26
I found out why, I used the wrong port.
Now it can relay my email through my ISP, but the receiver can't see the correct "From" address.
When I send the email, I set the "From" address to something like : 123@xyz.com, but the receiver sees something like this : my_user_Id_at_work@my_PC_id_at_work
It's not the From address I set. And it's not even a valid email address.
How to correct this ?
Frank
# 27
Your mail server at work is probably forcing the From address to be correct,so you can't send email with a forged From address. Generally, that's aVery Good Thing.You probably need to talk to your mail server administrator.
# 28
What's the relations among the following items :
smtp/smtps , ssl, protocol, auth, user_name/password ?
My understanding is :
ssl: protocol==smtps
non-ssl : protocol==smtp
auth : use user_name/password
non-auth : no need for user_name/password ( yet you can still supply them )
Can there be a combination of [ non-ssl + auth ] and [ ssl + non-auth ] ?
I just need a quick answer, thanks.
Frank
# 29
Yes, both combinations are allowed in general, although I don't think
Yahoo Mail or Gmail allow them.
You can authenticate using a non-secure connection, although it's
not a good idea since it exposes your authentication information to
anyone who can intercept your communication. You can also
connect using a non-secure connection, switch the connection into
secure mode (using the "STARTTLS" command), and then authenticate
safely. (I believe at least Gmail allows this.)
You can also connect using a secure connection but not authenticate
to the server, if the server allows it, of course. A server within a company
firewall might allow such connections, although in some cases it will only
allow you to send messages within the company. (Search for "relay" in
the FAQ.)
# 30
I have the following method that sends email, but I doubt if the logic is correct, it works, but it's not 100% correct when it comes to the relations of : user_name, password, Protocol, Ssl, Auth ...
Now it assumes Auth if there is a user_name, password, and if not Ssl, it will do : Transport.send(message)
Am I doing it the right way ? Need expert advice :
boolean Verbose=false,Debug=false,
Ssl=true,
Auth=true;
// Ssl=false,
// Auth=false;
// Ssl=false,
// Auth=true;
public void Send(String from,String to,String cc,String bcc,String host,String smtpPort,String subject,String body,String fileAttachment,String username,String password) throws Exception
{
String Attachments[];
Properties props=new Properties();// Create some properties and get the default Session
props.put("mail.smtp.host",host);
props.put("mail.smtp.port",smtpPort);
// props.put("mail.debug","true");
Session session=null;
Protocol=Ssl?"smtps":"smtp";
if (username != null && username.length()>0 && password != null && password.length()>0)
{
// props.put("mail.smtp.auth","true");
props.put("mail."+Protocol+".auth","true");
//session=Session.getDefaultInstance(props,new SMTPAuthenticator(username,password));
session=Session.getInstance(props,new SMTPAuthenticator(username,password));
}
//else session=Session.getDefaultInstance(props,null);
else session=Session.getInstance(props,null);
if (Debug) session.setDebug(true);
MimeMessage message=new MimeMessage(session);// Create a message
message.setFrom(new InternetAddress(from));
InternetAddress[] To_Address=InternetAddress.parse(to.replace(";",","),false);
message.setRecipients(Message.RecipientType.TO,To_Address);
InternetAddress[] Cc_Address=InternetAddress.parse(cc.replace(";",","),false);
message.addRecipients(Message.RecipientType.CC,Cc_Address);
InternetAddress[] Bcc_Address=InternetAddress.parse(bcc.replace(";",","),false);
message.addRecipients(Message.RecipientType.BCC,Bcc_Address);
message.setSubject(subject);
// You may need to encode the subject with this special method !
// message.setSubject(javax.mail.internet.MimeUtility.encodeText("Testing javamail with french : "));
message.setSentDate(new Date());
MimeBodyPart messageBodyPart=new MimeBodyPart();// Create the message part
messageBodyPart.setText(body); // Fill message
Multipart multipart=new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
if (fileAttachment != null)// Part two is attachment
{
if (fileAttachment.indexOf(",")!=-1) Attachments=fileAttachment.split(",");
else if (fileAttachment.indexOf(";")!=-1) Attachments=fileAttachment.split(";");
else Attachments=new String[]{fileAttachment};
for (int i=0;i<Attachments.length;i++)
{
if (new File(Attachments[i]).exists())
{
messageBodyPart=new MimeBodyPart();
FileDataSource fds=new FileDataSource(Attachments[i]);
messageBodyPart.setDataHandler(new DataHandler(fds));
messageBodyPart.setFileName(Attachments[i]);
multipart.addBodyPart(messageBodyPart);
}
}
}
message.setContent(multipart); // Put parts in message
// message.setText(text); // If there is no attachment
if (!Ssl) Transport.send(message);// Send the message
else
{
// The simple way to send a message is : Transport.send(message);
// But we're going to use some SMTP-specific features for demonstration purposes so we need to manage the Transport object explicitly.
SMTPTransport t=(SMTPTransport)session.getTransport(Protocol);
try
{
if (Auth) t.connect(host,username,password);
else t.connect();
t.sendMessage(message,message.getAllRecipients());
}
finally
{
if (Verbose) System.out.println("Response: "+t.getLastServerResponse());
t.close();
}
}
session=null;
}
>
# 31
Ok, I guess it's code review time! :-)
You never use smtpPort.
You don't need SMTPAuthenticator since you're using the
connect method that supplies the username and password
directly.
You can simplify the code by always using the t.connect/t.sendMessage path,
even for non-SSL.
It's not clear what you intend the relationship to be between the Auth variable
and a non-null username and password. You could probably derive the
former from the latter.
# 32
The smtpPort is used in props, which in turn is used to get a session, so user can specify any port they want, am I right ?
Are you saying if I use : "if (Auth) t.connect(host,username,password)" down there, then I don't need to use : SMTPAuthenticator at the beginning ?
To simplify, I can change :
if (!Ssl) Transport.send(message);// Send the message
else
{
// The simple way to send a message is : Transport.send(message);
// But we're going to use some SMTP-specific features for demonstration purposes so we need to manage the Transport object explicitly.
SMTPTransport t=(SMTPTransport)session.getTransport(Protocol);
try
{
if (Auth) t.connect(host,username,password);
else t.connect();
t.sendMessage(message,message.getAllRecipients());
}
finally
{
if (Verbose) System.out.println("Response: "+t.getLastServerResponse());
t.close();
}
}
Into this ? :
// The simple way to send a message is : Transport.send(message);
// But we're going to use some SMTP-specific features for demonstration purposes so we need to manage the Transport object explicitly.
SMTPTransport t=(SMTPTransport)session.getTransport(Protocol);
try
{
if (Auth) t.connect(host,username,password);
else t.connect();
t.sendMessage(message,message.getAllRecipients());
}
finally
{
if (Verbose) System.out.println("Response: "+t.getLastServerResponse());
t.close();
}
Frank
# 33
Oops, I missed that smtpPort usage. But yes, your change looks correct.
# 34
Is this statement true : if I use : "if (Auth) t.connect(host,username,password)" down there, then I don't need to use : SMTPAuthenticator at the beginning ?ThanksFrank
# 35
Again, I'm not clear on what you intend the relationship to be
between Auth and username/password. In one place you make
a decision based on whether username and password are non-null
and in another place you make a similar decision based on Auth.
As far as i can guess about what you're trying to achieve, you don't
need the SMTPAuthenticator.
# 36
That's because I wasn't clear how the process works, how do you know weather a mail server requires auth ? Do you get the info from the server admin ? In case of Yahoo, Gmail who do I ask ? Is there a way to automatically detect the requirement ?
So, I think I need to tell the program weather to auth or not, if it needs to, I then supply it with password, if it doesn't need to, just ignore the user_name and password, is this logical ?
Frank
# 37
You have to find out from the server admin what the requirements are forany particular server. Google and Yahoo publish the information you needon their web sites.
# 38
So there is no way to automatically detect the requirement during the connection ?Frank
# 39
Other than by trial and error, no.
# 40
Now I have 3 versions of code, which is the best ?
========================================= [ 1 ] =========================================
Protocol=ssl?"smtps":"smtp";
if (auth && username != null && password != null)
{
props.put("mail."+Protocol+".auth","true");
//session=Session.getDefaultInstance(props,new SMTPAuthenticator(username,password));
session=Session.getInstance(props,new SMTPAuthenticator(username,password));
}
//else session=Session.getDefaultInstance(props,null);
else session=Session.getInstance(props,null);
...
=== create message ===
...
SMTPTransport t=(SMTPTransport)session.getTransport(Protocol);
try
{
if (Auth) t.connect(host,username,password);
else t.connect();
t.sendMessage(message,message.getAllRecipients());
}
catch (Exception e)
{
...
}
========================================= [ 2 ] =========================================
Protocol=ssl?"smtps":"smtp";
if (auth && username != null && password != null)
{
props.put("mail."+Protocol+".auth","true");
//session=Session.getDefaultInstance(props,new SMTPAuthenticator(username,password));
session=Session.getInstance(props,new SMTPAuthenticator(username,password));
}
//else session=Session.getDefaultInstance(props,null);
else session=Session.getInstance(props,null);
...
=== create message ===
...
SMTPTransport t=(SMTPTransport)session.getTransport(Protocol);
try
{
t.connect();
t.sendMessage(message,message.getAllRecipients());
}
catch (Exception e)
{
...
}
========================================= [ 3 ] =========================================
Protocol=ssl?"smtps":"smtp";
if (auth) props.put("mail."+Protocol+".auth","true");
//session=Session.getDefaultInstance(props,null);
session=Session.getInstance(props,null);
...
=== create message ===
...
SMTPTransport t=(SMTPTransport)session.getTransport(Protocol);
try
{
if (Auth) t.connect(host,username,password);
else t.connect();
t.sendMessage(message,message.getAllRecipients());
}
catch (Exception e)
{
...
}
Also, when to use : Session.getDefaultInstance ?
And when to use : Session.getInstance ?
Frank
# 41
I would use #3, it's simpler. If you request authentication and don'tsupply a username or password, it will fail.Always use getInstance.(Knowing more about your application might cause me to choose adifferent answer.)
# 42
Alright, it seems the best solution is :
Protocol=ssl?"smtps":"smtp";
if (auth) props.put("mail."+Protocol+".auth","true");
session=Session.getInstance(props,null);
...
=== create message ===
...
SMTPTransport t=(SMTPTransport)session.getTransport(Protocol);
try
{
if (Auth && username != null && password != null) t.connect(host,username,password);
else t.connect();
t.sendMessage(message,message.getAllRecipients());
}
catch (Exception e)
{
...
}
# 43
What is this line for ?props.put("mail.mime.address.strict","false");or props.put("mail.mime.address.strict","true");Frank
# 44
See the javadocs for the javax.mail.internet package, and for the MimeMessage class.