In this article I'm going to show you how to send an email in the background without the user even knowing - the application will do everything behind the scenes.
Before we begin, you'll need to download a few files via the link below - this is a special version of the JavaMail API, which was written specifically for Android.
I'll be walking you through a Mail wrapper that I wrote, which makes it much easier to send emails and even add attachments if that's something you'd like to do.
Here is the full wrapper class below, which I'll go through step by step - keeping in mind that you'll have to add the fore-said files if you want this to work. Add them as external libraries - they need to be accessible by the Mail class.
import java.util.Date; import java.util.Properties; import javax.activation.CommandMap; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.activation.MailcapCommandMap; import javax.mail.BodyPart; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; public class Mail extends javax.mail.Authenticator { private String _username; private String _password; private String[] _to; private String _from; private String _port; private String _sport; private String _host; private String _subject; private String _body; private boolean _auth; private boolean _debuggable; private Multipart _multipart; public Mail() { _host = "smtp.gmail.com"; // default smtp server _port = "465"; // default smtp port _sport = "465"; // default socketfactory port _username = ""; // username _password = ""; // password _from = ""; // email sent from _subject = ""; // email subject _body = ""; // email body _debuggable = false; // debug mode on or off - default off _auth = true; // smtp authentication - default on _multipart = new MimeMultipart(); // There is something wrong with MailCap, javamail can not find a // handler for the multipart/mixed part, so this bit needs to be added. MailcapCommandMap mc = (MailcapCommandMap) CommandMap .getDefaultCommandMap(); mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html"); mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml"); mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain"); mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed"); mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822"); CommandMap.setDefaultCommandMap(mc); } public Mail(String user, String pass) { this(); _username = user; _password = pass; } public boolean send() throws Exception { Properties props = _setProperties(); if (!_username.equals("") && !_password.equals("") && _to.length > 0 && !_from.equals("") && !_subject.equals("") && !_body.equals("")) { Session session = Session.getInstance(props, this); MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(_from)); InternetAddress[] addressTo = new InternetAddress[_to.length]; for (int i = 0; i < _to.length; i++) { addressTo[i] = new InternetAddress(_to[i]); } msg.setRecipients(MimeMessage.RecipientType.TO, addressTo); msg.setSubject(_subject); msg.setSentDate(new Date()); // setup message body BodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setText(_body); _multipart.addBodyPart(messageBodyPart); // Put parts in message msg.setContent(_multipart); // send email Transport.send(msg); return true; } else { return false; } } public void addAttachment(String filename) throws Exception { BodyPart messageBodyPart = new MimeBodyPart(); DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(filename); _multipart.addBodyPart(messageBodyPart); } @Override public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(_username, _password); } private Properties _setProperties() { Properties props = new Properties(); props.put("mail.smtp.host", _host); if (_debuggable) { props.put("mail.debug", "true"); } if (_auth) { props.put("mail.smtp.auth", "true"); } props.put("mail.smtp.port", _port); props.put("mail.smtp.socketFactory.port", _sport); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback", "false"); return props; } // the getters and setters public String getBody() { return _body; } public void setBody(String _body) { this._body = _body; } public void sendTo(String[] _to) { this._to = _to; } public void sendFrom(String _from) { this._from = _from; } public void setSubject(String _subject) { this._subject = _subject; } // more of the getters and setters ….. }And now I'm going to go through each bit of code
public Mail() { _host = "smtp.gmail.com"; // default smtp server _port = "465"; // default smtp port _sport = "465"; // default socketfactory port _username = ""; // username _password = ""; // password _from = ""; // email sent from _subject = ""; // email subject _body = ""; // email body _debuggable = false; // debug mode on or off - default off _auth = true; // smtp authentication - default on _multipart = new MimeMultipart(); // There is something wrong with MailCap, javamail can not find a // handler for the multipart/mixed part, so this bit needs to be added. MailcapCommandMap mc = (MailcapCommandMap) CommandMap .getDefaultCommandMap(); mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html"); mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml"); mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain"); mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed"); mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822"); CommandMap.setDefaultCommandMap(mc); } public Mail(String user, String pass) { this(); _username = user; _password = pass; }
In this piece of code we initialise the properties, and setup the default values.
Also, we're setting up the mime types for javamail. I've also added a comment which describes why we need this.
And you've probably noticed that there are 2 constructors - one overrides the other, just incase the you want to pass the username and password when instantiating the class.
public boolean send() throws Exception { Properties props = _setProperties(); if (!_username.equals("") && !_password.equals("") && _to.length > 0 && !_from.equals("") && !_subject.equals("") && !_body.equals("")) { Session session = Session.getInstance(props, this); MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(_from)); InternetAddress[] addressTo = new InternetAddress[_to.length]; for (int i = 0; i < _to.length; i++) { addressTo[i] = new InternetAddress(_to[i]); } msg.setRecipients(MimeMessage.RecipientType.TO, addressTo); msg.setSubject(_subject); msg.setSentDate(new Date()); // setup message body BodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setText(_body); _multipart.addBodyPart(messageBodyPart); // Put parts in message msg.setContent(_multipart); // send email Transport.send(msg); return true; } else { return false; } }This is the most important method - here we're putting all the data from the properties and sending the mail.
public void addAttachment(String filename) throws Exception { BodyPart messageBodyPart = new MimeBodyPart(); DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(filename); _multipart.addBodyPart(messageBodyPart); }You can call this method at any time if you want to add an attachment, but make sure you call it before the send method.
private Properties _setProperties() { Properties props = new Properties(); props.put("mail.smtp.host", _host); if (_debuggable) { props.put("mail.debug", "true"); } if (_auth) { props.put("mail.smtp.auth", "true"); } props.put("mail.smtp.port", _port); props.put("mail.smtp.socketFactory.port", _sport); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback", "false"); return props; }Here we're setting up the properties for the mail retrieval - defaulting to SMTP authentication. Also keep in mind that this is all defaulted to connect to the Gmail (Google) SMTP server. Below is an example of how to use the Mail wrapper, in an Android activity.
@Override public void onClick(View v) { // TODO Auto-generated method stub if (mEmail.getText().toString().equals( appPrefs.getEmail())) { Mail m = new Mail("email@gmail.com", "password"); String[] toArr = {mEmail.getText().toString()}; m.sendTo(toArr); m.sendFrom("email@gmail.com"); m.setSubject("Password"); m.setBody("This is your password : " + appPrefs.getPassword()); try { m.addAttachment("/sdcard/filelocation"); if(m.send()) { Toast.makeText(password.this, "Email was sent successfully.", Toast.LENGTH_LONG).show(); } else { Toast.makeText(password.this, "Email was not sent.", Toast.LENGTH_LONG).show(); } } catch(Exception e) { //Toast.makeText(MailApp.this, "There was a problem sending the email.", Toast.LENGTH_LONG).show(); Log.e("Password", "Could not send email", e); } } else { Toast .makeText( getBaseContext(), "This is not that email which you enter when create account", Toast.LENGTH_LONG).show(); } } });
13 comments:
can you send me project because in my project NetworkOnMainThreadException error occur.My Email Address is:
patel.varun89@gmail.com
Thanks.
can you send me project because i have many probles to compile...
my email is ribasnicolas@gmail.com
I m trying to send a file and a html template through this mail...
I can successfully attach a file but unable to send the html template..
Can you tell me , how it is possible to send the Html template..
can you send me project because i have many probles to compile...
my email is : gvnbsg@gmail.com
My friend .. Can you send me the project? Good day!
Hi all,
In this code we are stroing the password in our java file.
But here is a chance to steal the password by using de-compiler.
When we hardcode this email Id in our client code, if the end-user will be in different countries and our app will use the same email id to communicate. Due to this Gmail will force you to change the password due to account access from different IP address.
How to get ride of these security issue?
Please help me out on this?
hai..why there is a problem when i try to sent the email? it show the exception e..may i know what is the problem? is there any setting i need to check in my android?
can you send me the project i have many errors in my project
my email id is:j.princesolomon@gmail.com
Thanks!!
can you please send the me the project because i've tried it yet the app is stopping unfortunately. academic.sakshi.cs2@gmail.com
1.Convert msg in MimeMessage msg = new MimeMessage(session); to be final.
2.Wrap Transport.send(msg); as new Thread(new Runnable() {
@Override
public void run() {
Transport.send(msg);
}
}).start();
after doing this ,code works fine :)
thanks a lot bro....its working fiiiinnnneee...if u seen toast msg but not receiving mail in your gmail account then change your mobile device quickly... :) :)
AuthenticationFailedException
12-13 15:54:26.272 8751-8971/dev.ch8n.emailer W/System.err: at javax.mail.Service.connect(Service.java:319)
12-13 15:54:26.272 8751-8971/dev.ch8n.emailer W/System.err: at javax.mail.Service.connect(Service.java:169)
12-13 15:54:26.272 8751-8971/dev.ch8n.emailer W/System.err: at javax.mail.Service.connect(Service.java:118)
12-13 15:54:26.272 8751-8971/dev.ch8n.emailer W/System.err: at javax.mail.Transport.send0(Transport.java:188)
12-13 15:54:26.272 8751-8971/dev.ch8n.emailer W/System.err: at javax.mail.Transport.send(Transport.java:118)
12-13 15:54:26.272 8751-8971/dev.ch8n.emailer W/System.err: at dev.ch8n.androidEmailer.java.GMailSender$1.run(GMailSender.java:69)
12-13 15:54:26.272 8751-8971/dev.ch8n.emailer W/System.err: at java.lang.Thread.run(Thread.java:818)
Post a Comment