Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android app to send Email with attachment using Java Mail API

I am trying to make a simple email app using Java Mail Android API (https://code.google.com/p/javamail-android/) which will send mail with an attachment. But my approach isn't working. It successfully sends the email text but doesn't add the attachment with the email. I have added one image button to select a file for attachment. I am using Intent to select a file. Also added another button to send email.

At first by clicking on image button I am trying to select file and get the file path for the attachment. Then I am setting the file path to sendmail method for sending the mail with this attachment.

what I am doing is given below:

Email.java

package com.android.imran.emailapp003;

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;


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;
        }
    }

    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(_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.android.imran.emailapp003;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Log;

import java.util.List;

public class ProcessEmail extends AsyncTask {

    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();
    }

}

MainActivity.java

package com.android.imran.emailapp003;

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 {

    private static int FILE_SELECT_CODE;
    private static int SELECT_PICTURE;
    String FilePath;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_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("*******@gmail.com");
                toEmails.add("*******@live.com");
                String emailSubject = "This is an email sent using my Mail JavaMail wrapper from an Android device.";
                String emailBody= "Email body.";
                new ProcessEmail(MainActivity.this).execute(
                        fromEmail, fromPassword, toEmails, emailSubject, emailBody, FilePath);
            }
        });

        ImageButton selectFile= (ImageButton) 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) {
        if ((requestCode == FILE_SELECT_CODE) && (resultCode == -1)) {
            FilePath = data.getData().getPath();
            //Toast.makeText(this, FilePath, Toast.LENGTH_SHORT).show();
        }
    }
}

Please help me to fix it out.

Update: In my Genymotion emulator I've selected a file. My app shows the file path as /external/images/images/14 in toast message.

Then when I click on the send button to send the email. I got the following error:

11-17 04:47:46.887  25788-26024/com.android.imran.emailapp003 E/SendMailTask﹕ IOException while sending message
    javax.mail.MessagingException: IOException while sending message;
    nested exception is:
    java.io.FileNotFoundException: /external/images/media/14: open failed: ENOENT (No such file or directory)
            at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:676)
            at javax.mail.Transport.send0(Transport.java:189)
            at javax.mail.Transport.send(Transport.java:118)
            at com.android.imran.emailapp003.Email.send(Email.java:105)
            at com.android.imran.emailapp003.ProcessEmail.doInBackground(ProcessEmail.java:42)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)
     Caused by: java.io.FileNotFoundException: /external/images/media/14: open failed: ENOENT (No such file or directory)
            at libcore.io.IoBridge.open(IoBridge.java:409)
            at java.io.FileInputStream.<init>(FileInputStream.java:78)
            at javax.activation.FileDataSource.getInputStream(FileDataSource.java:110)
            at javax.activation.DataHandler.writeTo(DataHandler.java:318)
            at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1403)
            at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:874)
            at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:444)
            at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:102)
            at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:897)
            at javax.activation.DataHandler.writeTo(DataHandler.java:330)
            at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1403)
            at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1745)
            at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:636)
            at javax.mail.Transport.send0(Transport.java:189)
            at javax.mail.Transport.send(Transport.java:118)
            at com.android.imran.emailapp003.Email.send(Email.java:105)
            at com.android.imran.emailapp003.ProcessEmail.doInBackground(ProcessEmail.java:42)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)
     Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
            at libcore.io.Posix.open(Native Method)
            at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
            at libcore.io.IoBridge.open(IoBridge.java:393)
            at java.io.FileInputStream.<init>(FileInputStream.java:78)
            at javax.activation.FileDataSource.getInputStream(FileDataSource.java:110)
            at javax.activation.DataHandler.writeTo(DataHandler.java:318)
            at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1403)
            at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:874)
            at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:444)
            at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:102)
            at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:897)
            at javax.activation.DataHandler.writeTo(DataHandler.java:330)
            at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1403)
            at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1745)
            at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:636)
            at javax.mail.Transport.send0(Transport.java:189)
            at javax.mail.Transport.send(Transport.java:118)
            at com.android.imran.emailapp003.Email.send(Email.java:105)
            at com.android.imran.emailapp003.ProcessEmail.doInBackground(ProcessEmail.java:42)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)
11-17 04:48:58.359  25788-25788/com.android.imran.emailapp003 W/EGL_genymotion﹕ eglSurfaceAttrib not implemented

I ran the application into my android device. I selected a file and my app showed the file path as /document/images:52721 in toast message. But the actual path of the file is "/Internal Storage/DCIM/Camera/01.jpg"

I think my application doesn't getting the actual path for the attachment file. How can get the actual path for the attachment file?

like image 456
Abdullah Al Imran Avatar asked Nov 17 '15 08:11

Abdullah Al Imran


1 Answers

Try this to get your file path:

   Uri selectedData = data.getData();
   String[] filePathcolumn = {MediaStore.Files.FileColumns.DATA};

   Cursor cursor = getContentResolver().query(selectedData, filePathcolumn, null, null, null);
   cursor.moveToFirst();
   Log.d(TAG, DatabaseUtils.dumpCursorToString(cursor));
   columnindex = cursor.getColumnIndex(filePath[0]);
   attachFile = selectedData.toString();
   filePath = Uri.parse(attachFile);    
   cursor.close();
like image 195
user9017909 Avatar answered Oct 24 '22 14:10

user9017909