I've been troubleshooting for a while and may be suffering from the XY problem so this will be fairly descriptive.
Goal: Send a simple email message on the click of a button without leveraging external mail app.
Research led to the JavaMail API, which was successfully compiled, tested, and executed on a personal computer.
So after spending some time reading answers here I followed these steps to add the library.
Right click on App -> New Module -> Import .JAR/.AAR Package.
Utilize ellipsis button to find and add the jar.
App -> Module Settings
Under Modules, App -> Dependencies -> Add -> Module Dependency -> Selecting the JAR module.
In addition to this, I also did the following:
Ensured the app module's build.gradle included the dependency (In this case, listed as compile project(':javax.mail')
On project root, use and run gradlew clean as well as gradlew build
This has been tried a few other, failing ways but these are the latest series of steps. Android Studio detects the files, but when executed the app crashes with a NoClassDefFoundError. Intuition says the problem is classpath but after trying several different but ineffective solutions for this it's time to yield to more experienced advice.
For reference:
MainActivity:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button testButton = (Button) findViewById(R.id.emailButton);
testButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Emailer.send(getApplicationContext());
}
});
}
}
Emailer:
import android.content.Context;
import android.widget.Toast;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class Emailer {
public static void send(Context context) {
// Recipient's email
String recipient = "myemail#gmail.com";
// Sender information
String sender = "myemail#gmail.com";
final String username = "myUsername";
final String password = "myPassword";
String host = "smtp.gmail.com";
Properties properties = new Properties();
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.socketFactory.port", "465");
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.port", "25");
Session session = Session.getInstance(properties,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
// constructing the email
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(sender));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
message.setSubject("Email Test");
message.setText("Testing the email capability using JavaMailAPI on Android");
// Sending
Transport.send(message);
Toast.makeText(context, R.string.email_success, Toast.LENGTH_SHORT).show();
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}
Related
I'm trying to send an email automatically, without user confirmation in my Android App. I'm trying to do with Javamail, but when I try my app on my phone, it's close with the typical "APP STOPPED, Open again" Android message.
My code is:
SEND MAIL CLASS:
package com.android.mdw.demo;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import android.util.Log;
public class EnviarEmail {
public static String emailEnvio = "XXX#gmail.com";
public static String passwordEmailEnvio = "#XXX";
public void EnviarEmail(String Mensaje, String Asunto, String email) {
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(emailEnvio, passwordEmailEnvio);
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(emailEnvio));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(email));
message.setSubject(Asunto);
message.setText(Mensaje);
Transport.send(message);
} catch (MessagingException e) {
Log.w("ERROR", "No se ha podido enviar el email de confirmación.");
}
}
}
NOTICE MAIL CLASS:
package com.android.mdw.demo;
public class EmailAviso {
public void EmailAviso () {
String Mensaje = "CUERPO";
String Asunto = "ASUNTO";
String email = "AQUIENVA#gmail.com";
EnviarEmail EnviarEmail = new EnviarEmail();
EnviarEmail.EnviarEmail(Mensaje, Asunto, email);
}
}
EXTRACT FROM MAIN CLASS:
boolean PRUEBA=true;
boolean PRUEBA1=true;
if(PRUEBA==true && PRUEBA1==true) {
EmailAviso EmailAviso = new EmailAviso();
EmailAviso.EmailAviso();
}
And the log I recive in AS is:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.mdw.demo, PID: 18001
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74)
at java.net.InetAddress.getLocalHost(InetAddress.java:816)
at javax.mail.internet.InternetAddress.getLocalAddress(InternetAddress.java:517)
at javax.mail.internet.UniqueValue.getUniqueMessageIDValue(UniqueValue.java:99)
at javax.mail.internet.MimeMessage.updateMessageID(MimeMessage.java:2054)
at javax.mail.internet.MimeMessage.updateHeaders(MimeMessage.java:2076)
at javax.mail.internet.MimeMessage.saveChanges(MimeMessage.java:2042)
at javax.mail.Transport.send(Transport.java:117)
at com.android.mdw.demo.EnviarEmail.EnviarEmail(EnviarEmail.java:41)
at com.android.mdw.demo.EmailAviso.EmailAviso(EmailAviso.java:10)
at com.android.mdw.demo.Main.onSensorChanged(Main.java:77)
at android.hardware.SystemSensorManager$SensorEventQueue.dispatchSensorEvent(SystemSensorManager.java:699)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:323)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
you are trying to send email from main thread which is not allowed, try creating separate worker thread for sending email. Try something like following:
new Thread(new Runnable() {
#Override
public void run() {
if(PRUEBA==true && PRUEBA1==true) {
EmailAviso EmailAviso = new EmailAviso();
EmailAviso.EmailAviso();
}
}
}).start();
Sending email directly from Android is considered as a bad practice, as you'll have to store your email and password in the source code, and a simple APK decomile can compromise the credentials.
If you want to send email without user interaction, you'll have to use an external API to send mail, or you'll have to develop your own API using any server stack such as PHP,nodejs, JSP etc.
I've created a simple library named SafeMail to fix this issue. All you have to do is to get your API Key from here and use it like in this example.
Sorry for the minimal documentation. Feel free to shoot queries in the comments.
I have a regular Java Application that works with Javamail. As in, if I just run it in a Main(String[] args) it will work but if I'm running it from a webapp, specifically VAADIN with Tomcat (AND Jetty), I always get a java.net.SocketException: network is unreachable: connect
I can ping the MSExchange server. And the regular program works.
In eclipse, I tried following this guide by changing the server.xml and web.xml settings, but after adding in all th changes, I still get the same error.
This is the Java Application that works in Eclipse, it will send an email using the MSExchange server we have. Are there specific ports I need to add? I've tried to force Tomcat to use IPV4 by adding 0.0.0.0 to all my connectors but that didn't do anything.
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
import javax.mail.Session;
import java.text.SimpleDateFormat;
public class SendEmail {
public static void main(String[] args) {
//Creates a connection with the Exchange Server.
String smtpHostServer = "MSExchangeServerName";
Properties props = System.getProperties();
props.put("mail.smtp.host", smtpHostServer);
props.put("mail.smtp.auth", "false");
props.put("mail.smtp.socketFactory.port", "25");
props.put("java.net.preferIPv4Stack","True");
Session session = Session.getInstance(props, null);
String todayStr = new SimpleDateFormat("MM-dd-yyyy").format(new Date());
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, 14);
Date d = c.getTime();
String dateStr = new SimpleDateFormat("MM/dd/yyyy").format(d);
SendEmailUtility.sendEmail(session, "email#host.com", "Test <b>Email</b>");
Here is the SendEmailUtility:
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
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 SendEmailUtility {
public static void sendEmail(Session session, String toEmail, String subject, String body){
try
{
//Create a default MimeMessage object.
Message message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress("blah#test.com"));
// Set To: header field of the header.
message.setRecipients(Message.RecipientType.TO,InternetAddress.parse(toEmail));
// Set Subject: header field
message.setSubject(subject);
// This mail has 2 part, the BODY and the embedded image
MimeMultipart multipart = new MimeMultipart("related");
// first part (the html)
BodyPart messageBodyPart = new MimeBodyPart();
String htmlText = "<img src=\"cid:image\"><p>"+body;
messageBodyPart.setContent(htmlText, "text/html");
// add it
multipart.addBodyPart(messageBodyPart);
// second part (the image)
messageBodyPart = new MimeBodyPart();
String fdsImg;
fdsImg = "c:\download.jpg";
DataSource fds = new FileDataSource(fdsImg);
messageBodyPart.setDataHandler(new DataHandler(fds));
messageBodyPart.setHeader("Content-ID", "<image>");
// add image to the multipart
multipart.addBodyPart(messageBodyPart);
// put everything together
message.setContent(multipart);
// Send message
Transport.send(message); //ERROR HAPPENS HERE ON TOMCAT
}
catch (Exception e) {
e.printStackTrace();
}
}
}
This is the exactly same copy pasted code in the webapp with the exact same EmailUtils above, only that this version DOESN'T WORK.
btnSendEmail.addClickListener(new ClickListener(){
#Override
public void buttonClick(ClickEvent event) {
try {
String smtpHostServer = "MSExchangeServerName";
Properties props = System.getProperties();
props.put("mail.smtp.host", smtpHostServer);
props.put("mail.smtp.auth", "false");
props.put("mail.smtp.socketFactory.port", "25");
props.put("java.net.preferIPv4Stack","True");
Session session = Session.getInstance(props, null);
String todayStr = new SimpleDateFormat("MM-dd-yyyy").format(new Date());
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, 14);
Date d = c.getTime();
String dateStr = new SimpleDateFormat("MM/dd/yyyy").format(d);
SendEmailUtility.sendEmail(session, "blah#test.com", "test <b>email");
} catch (Exception e) {
e.printStackTrace();
Notification.show("Error sending the email", Notification.Type.ERROR_MESSAGE);
}
}
});
layout.addComponent(btnSendEmail);
My Stacktrace:
javax.mail.MessagingException: Could not connect to SMTP host: MSExchangeName, port: 25;
nested exception is:
java.net.SocketException: Network is unreachable: connect
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1972)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:642)
at javax.mail.Service.connect(Service.java:295)
at javax.mail.Service.connect(Service.java:176)
at javax.mail.Service.connect(Service.java:125)
at javax.mail.Transport.send0(Transport.java:194)
at javax.mail.Transport.send(Transport.java:124)
at org.test.EmailUtils.sendEmail(EmailUtils.java:57)
Are there any other options I have to do or that I might not have done correctly? As a shot in the dark, I tried looking up eclipse, javamail, tomcat and I got this question and added the Javamail jar to my Tomcat Lib folder and also in my classpath. I still get the cannot connect error.
When I Right Click > Run as >Run on server, I tried to see if Tomcat was running on a system account, but when I checked in Task Manager, it had my Username under here:
Does this mean it has access to the network? Or something is still blocked? Or I need to add proxy settings specifically for Tomcat?
Sounds like a firewall or anti-virus problem. The JavaMail FAQ has connection debugging tips.
I'm not a very experienced coder, but I have been learning. Right now I am in the process of writing a test email bot to, well, send emails. I ran across a problem when I tried to make it so you could type out the message and subject of the email in a JOptionPane Dialog box.
Here is the code, look at the Strings at the top and the messageobjs at the bottom..
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.swing.JOptionPane;
public class Ebot2
{
public static void main(String[] args)
{
String Dest;
Dest = JOptionPane.showInputDialog("Who would you like to message?");
String Subject;
Subject = JOptionPane.showInputDialog("What is the message subject?");
String Message;
Message = JOptionPane.showInputDialog("What is the message?");
String sendrmailid = "email#gmail.com";
final String uname = "email";
final String pwd = "pass";
Properties propvls = new Properties();
propvls.put("mail.smtp.auth", "true");
propvls.put("mail.smtp.starttls.enable", "true");
propvls.put("mail.smtp.host", "smtp.gmail.com");
propvls.put("mail.smpt.port", "25");
Session sessionobj = Session.getInstance(propvls,
new javax.mail.Authenticator()
{
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(uname, pwd);
}
});
try
{
Message messageobj = new MimeMessage(sessionobj);
messageobj.setFrom(new InternetAddress(sendrmailid));
messageobj.setRecipients(Message.RecipientType.TO,InternetAddress.parse(Dest));
messageobj.setSubject(Subject);
messageobj.setText(Message);
Transport.send(messageobj);
System.out.println("Your email sent successfully....");
}
catch (MessagingException exp)
{
throw new RuntimeException(exp);
}
}
}
sorry for the shit formatting, the code block thing was difficult. Anyways the error Im getting started, after I changed the setSubject and setText to Strings that are entered through a JOptionPane. And the error is..
Ebot2.java:53: error: cannot find symbol
messageobj.setRecipients(Message.RecipientType.TO,InternetAddress.parse(Dest));
^
symbol: variable RecipientType
location: variable Message of type String
1 error
Thanks to anyone who answers, I really need help on this!
I fixed it guys. The problem was I had the String for the message set as Message (same problem with subject) which was also a variable. So I just renamed the string and it all worked. Thanks for the help anyways, glad to know I can go to this site for questions.
Next I'm going to try to figure out how to send the email multiple times, but I should be able to figure that out on my own.
I am quite new in programming, sorry for weak explanation. I have tried with almost all available answers in google. but could not figure out why the error is coming.The purpose of this code is to attach a file and send it to a email address. I dont have any email server.
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
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 SendEmailMain {
public static void main(String[] args) {
final String username = "myusername#gmail.com";
final String password = "mypassword";
String emailID = "receiversUserName#yahoo.com";
Properties props = new Properties();
props.put("mail.smtp.starttls.enable", true);
props.put("mail.smtp.auth", true);
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(emailID));
message.setSubject("Testing Subject");
message.setText("PFA");
MimeBodyPart messageBodyPart = new MimeBodyPart();
Multipart multipart = new MimeMultipart();
messageBodyPart = new MimeBodyPart();
String file = "snap1.jpg";
String fileName = "attachmentName";
DataSource source = new FileDataSource(file);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(fileName);
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
System.out.println("Sending");
Transport.send(message);
System.out.println("Done");
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
Error message in eclipse console
Sending
com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first. of6sm3574020lbb.11 - gsmtp
at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1388)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:959)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:583)
at javax.mail.Transport.send0(Transport.java:169)
at javax.mail.Transport.send(Transport.java:98)
at me.screenful.screenshot.ScreenShotTaker.SendEmailMain.main(SendEmailMain.java:70)
I have found why it was not working. Because I copied the code from google to my project. In the code
props.put("mail.smtp.starttls.enable", true);
props.put("mail.smtp.auth", true);
value true was not in inverted comma. It should be like this
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth", "true");
If error come "530 5.7.0 Must issue a STARTTLS command first." at run time.
In IDE:
Right click the project. Click Run as then Run Configurations.
You can set the parameters "-Dmail.smtp.starttls.enable=true" in the (X)= Arguments tab in the VM Arguments box.
Click Run button.
or
At Command prompt:
You're giving parameters to java program
java -Dmail.smtp.starttls.enable=true <>.java
I am new to android development . I am making a small email client using javamail api . I am not able to find a solution on how will that activity start . Below is my code file for email manager which I want to start when I run the application .
I just need a way to start this , I am really confused with the android activities and have clue how to implement them
Thanks in Advance :)
package com.mailtest.android;
import android.app.Activity;
import android.os.Bundle;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import android.view.View;
import android.os.Bundle;
import android.content.Intent;
import android.widget.Button;
public class EmailManager extends Activity {
**/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);**
}
private String stmpHost = "smtp.gmail.com";
private String mailServer = "imap.gmail.com";
private EmailAccount account;
private Session smtpSession;
private Session imapSession;
private Folder inbox;
private Store store;
public EmailManager(String username, String password, String urlServer, String stmpHost, String mailServer) {
account = new EmailAccount(username, password, urlServer);
this.stmpHost = stmpHost;
this.mailServer = mailServer;
initProtocol();
}
private void initProtocol() {
EmailAuthenticator authenticator = new EmailAuthenticator(account);
Properties props1 = new Properties();
props1.setProperty("mail.transport.protocol", "smtps");
props1.setProperty("mail.host", stmpHost);
props1.put("mail.smtp.auth", "true");
props1.put("mail.smtp.port", "465");
props1.put("mail.smtp.socketFactory.port", "465");
props1.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props1.put("mail.smtp.socketFactory.fallback", "false");
props1.setProperty("mail.smtp.quitwait", "false");
smtpSession = Session.getDefaultInstance(props1, authenticator);
Properties props2 = new Properties();
props2.setProperty("mail.store.protocol", "imaps");
props2.setProperty("mail.imaps.host", mailServer);
props2.setProperty("mail.imaps.port", "993");
props2.setProperty("mail.imaps.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props2.setProperty("mail.imaps.socketFactory.fallback", "false");
imapSession = Session.getInstance(props2);
}
public Message[] getMails() throws MessagingException {
store = imapSession.getStore("imaps");
store.connect(mailServer, account.username, account.password);
inbox = store.getFolder("Inbox");
inbox.open(Folder.READ_ONLY);
Message[] result = inbox.getMessages();
return result;
}
public void close() {
//Close connection
try {
inbox.close(false);
store.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized void sendMail(String subject, String body, String sender, String recipients) throws Exception {
MimeMessage message = new MimeMessage(smtpSession);
DataHandler handler = new DataHandler(new ByteArrayDataSource(body.getBytes(), "text/plain"));
message.setSender(new InternetAddress(sender));
message.setSubject(subject);
message.setDataHandler(handler);
if (recipients.indexOf(',') > 0)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
else
message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
Transport.send(message);
}
}
AND THIS IS MY MAIN.XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
/>
</LinearLayout>
First of, you might want to have the email manager in its own class since it´s not a necessity to extend it as an Activity. However, to answer your question you could have a look at http://developer.android.com/reference/android/app/Activity.html
This is just an example and let´s say that the activity that should start the other activity is called MainActivity.
Then put this in MainActivity:
startActivity(new Intent(MainActivity.this, EmailManager.class));
Just remember to put the Email Manager as an Activity in your AndroidManifest.xml
<activity android:name=".EmailManager"/>
Possible duplicate answer, more can be found here: How to start activity in another application?
Go back to read this: http://developer.android.com/reference/android/app/Activity.html
Do not extend Activity for your EmailManager, you don't need to, as EmailManager doesn't interact with the user interface and doesn't depend on any context.
Implement a separate Activity where you call the relevant EmailManager methods from the Activity methods (OnCreate, OnResume, etc.) OnCreate is where your activity starts by the way
When you get a better understanding of the lifecycle of android components you are better of moving things from your activity to a service: http://developer.android.com/reference/android/app/Service.html
This is again because you have no ui-interaction from your EmailManager, and the type of work your EmailManager does is better suited for a service.