Leenah Leenah -4 years ago 109
Android Question

Java Mail API not working with attachment

I need to fix my code, it is not sending after adding attachment code

Email.java

package com.leenah.app;
import java.util.Date;
import java.util.List;
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;

/**
* Created by Leenah 21/03/2017.
*/

public class Email extends javax.mail.Authenticator {
private String _user;
private String _pass;

private List<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 Email() {
_host = "smtp.gmail.com"; // default smtp server
_port = "465"; // default smtp port
_sport = "465"; // default socketfactory port

_user = ""; // username
_pass = ""; // 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 Email(String user, String pass) {
this();

_user = user;
_pass = pass;
}

public boolean send() throws Exception {
Properties props = _setProperties();

if(!_user.equals("") && !_pass.equals("") && _to.size() > 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.size()];
for (int i = 0; i < _to.size(); i++) {
addressTo[i] = new InternetAddress(_to.get(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;
}
}
BodyPart messageBodyPart = new MimeBodyPart();

public void addAttachment(String filename) throws Exception {
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);

_multipart.addBodyPart(messageBodyPart);


}

@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(_user, _pass);
}

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 List<String> getTo(){
return _to;
}
public void setTo(List<String> toArr) {
this._to = toArr;
}

public String getFrom(){
return _from;
}
public void setFrom(String from){
this._from = from;
}

public String getSubject(){
return _subject;
}
public void setSubject(String string) {
this._subject = string;
}


}

ProcessEmail.java

package com.leenah.app;
private ProgressDialog statusDialog;
private Activity sendMailActivity;

public ProcessEmail(Activity activity) {
sendMailActivity = activity;
}

protected void onPreExecute() {
statusDialog = new ProgressDialog(sendMailActivity);
statusDialog.setMessage("Getting ready...");
statusDialog.setIndeterminate(false);
statusDialog.setCancelable(false);
statusDialog.show();
}

@Override
protected Object doInBackground(Object... args) {
try {
Log.i("SendMailTask", "About to instantiate GMail...");
publishProgress("Processing input....");
Email sendMail = new Email(args[0].toString(), args[1].toString());

publishProgress("Preparing mail message....");
sendMail.setFrom(args[0].toString());
sendMail.setTo((List<String>) args[2]);
sendMail.setSubject(args[3].toString());
sendMail.setBody(args[4].toString());
sendMail.addAttachment(args[5].toString());

publishProgress("Sending email....");
sendMail.send();

publishProgress("Email Sent.");
Log.i("SendMailTask", "Mail Sent.");
} catch (Exception e) {
publishProgress(e.getMessage());
Log.e("SendMailTask", e.getMessage(), e);
}
return null;
}

@Override
public void onProgressUpdate(Object... values) {
statusDialog.setMessage(values[0].toString());

}

@Override
public void onPostExecute(Object result) {
statusDialog.dismiss();
}

}


This main activity for sending mail with attachment
MainActivity.java

package com.leenah.app;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MainActivity extends AppCompatActivity {

String FilePath;

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);

Button addImage = (Button) findViewById(R.id.send_email);
addImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String fromEmail = "*******@gmail.com";
String fromPassword = "*******";
List<String> toEmails = new ArrayList();
toEmails.add("*******@hotmail.com");
toEmails.add("*******@hotmail.com");
String emailSubject = "This is an email sent using my Mail JavaMail wrapper from an Android device.";
String emailBody= "Email body.";




new ProcessEmail(Send.this).execute(
fromEmail, fromPassword, toEmails, emailSubject, emailBody, FilePath);
}
});

Button selectFile= (Button) findViewById(R.id.selectFile);
selectFile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, FILE_SELECT_CODE);
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if ((requestCode == FILE_SELECT_CODE) && (resultCode == RESULT_OK)) {
Uri uri = data.getData();
FilePath = getRealPathFromURI(uri);
Toast.makeText(this,FilePath+ "", Toast.LENGTH_SHORT).show();

}

}


private String getRealPathFromURI(Uri uri){
String filePath="";
String[] filePahColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(uri, filePahColumn, null, null, null);
if (cursor != null) {
if(cursor.moveToFirst()){
int columnIndex = cursor.getColumnIndex(filePahColumn[0]);
filePath = cursor.getString(columnIndex);
Toast.makeText(this,columnIndex+"....."+ "", Toast.LENGTH_SHORT).show();
}
cursor.close();
}

return filePath;
}

}


When I click send button: I got the following error:

E/SendMailTask: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a
null object reference
at com.philosophy.great.ProcessEmail.doInBackground(ProcessEmail.java:43)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
03-21 13:41:10.032 968-968/? E/fast-dormancy: [FDM]: rrc_state=0
03-21 13:41:10.065 968-968/? E/fast-dormancy: [FDM]: rrc_state=0

Answer Source

The directory you are trying to access might not exist yet. According to API, the code ensures the directory exists using mkdirs()

File path = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");

try {
    // Make sure the Pictures directory exists.
    path.mkdirs();
...

Hope it helps.

EDIT

Meanwhile make sure that,

  1. Your filename is correct
  2. You are not writing to the root folder
  3. Your path is correct
  4. You have give the appropriate permissions

EDIT # 2

You are getting the FilePath in a wrong way. Change your onActivityResult with below one

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if ((requestCode == FILE_SELECT_CODE) && (resultCode == RESULT_OK)) {
        Uri uri = data.getData();
        FilePath = getRealPathFromURI(uri);
    }

}


private String getRealPathFromURI(Uri uri){
    String filePath = "";
    String[] filePahColumn = {MediaStore.Images.Media.DATA};
    Cursor cursor = getContentResolver().query(uri, filePahColumn, null, null, null);
    if (cursor != null) {
        if(cursor.moveToFirst()){
            int columnIndex = cursor.getColumnIndex(filePahColumn[0]);
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();
    }
    return filePath;
}

Now use this FilePath.

EDIT 3

Change your intent call to this.

Intent intent = new Intent(
                        Intent.ACTION_PICK,
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download