Sending Email in Android using JavaMail API without using the default/built-in app
我正在尝试在Android中创建一个邮件发送应用程序。
如果我使用:
1 | Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); |
这将启动内置的Android应用程序;我正在尝试不使用此应用程序直接单击"邮件发送"按钮。
使用JavaMail API使用Gmail身份验证在Android中发送电子邮件。
创建示例项目的步骤:mail发送活动.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class MailSenderActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button send = (Button) this.findViewById(R.id.send); send.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { try { GMailSender sender = new GMailSender("[email protected]","password"); sender.sendMail("This is Subject", "This is Body", "[email protected]", "[email protected]"); } catch (Exception e) { Log.e("SendMail", e.getMessage(), e); } } }); } } |
gmail发送程序.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | public class GMailSender extends javax.mail.Authenticator { private String mailhost ="smtp.gmail.com"; private String user; private String password; private Session session; static { Security.addProvider(new com.provider.JSSEProvider()); } public GMailSender(String user, String password) { this.user = user; this.password = password; Properties props = new Properties(); props.setProperty("mail.transport.protocol","smtp"); props.setProperty("mail.host", mailhost); props.put("mail.smtp.auth","true"); props.put("mail.smtp.port","465"); props.put("mail.smtp.socketFactory.port","465"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback","false"); props.setProperty("mail.smtp.quitwait","false"); session = Session.getDefaultInstance(props, this); } protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user, password); } public synchronized void sendMail(String subject, String body, String sender, String recipients) throws Exception { try{ MimeMessage message = new MimeMessage(session); 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); }catch(Exception e){ } } public class ByteArrayDataSource implements DataSource { private byte[] data; private String type; public ByteArrayDataSource(byte[] data, String type) { super(); this.data = data; this.type = type; } public ByteArrayDataSource(byte[] data) { super(); this.data = data; } public void setType(String type) { this.type = type; } public String getContentType() { if (type == null) return"application/octet-stream"; else return type; } public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(data); } public String getName() { return"ByteArrayDataSource"; } public OutputStream getOutputStream() throws IOException { throw new IOException("Not Supported"); } } } |
jsseprovider.java版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the"License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an"AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Alexander Y. Kleymenov * @version $Revision$ */ import java.security.AccessController; import java.security.Provider; public final class JSSEProvider extends Provider { public JSSEProvider() { super("HarmonyJSSE", 1.0,"Harmony JSSE Provider"); AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() { public Void run() { put("SSLContext.TLS", "org.apache.harmony.xnet.provider.jsse.SSLContextImpl"); put("Alg.Alias.SSLContext.TLSv1","TLS"); put("KeyManagerFactory.X509", "org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl"); put("TrustManagerFactory.X509", "org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl"); return null; } }); } } |
在以下链接中添加3个jar到您的Android项目中
- 小精灵
- 活化罐
- 加法罐
单击此处-如何添加外部JAR
别忘了在清单中添加这一行:
1 | <uses-permission android:name="android.permission.INTERNET" /> |
只需单击下面的链接,即可更改安全性较低的应用程序的帐户访问权限。https://www.google.com/settings/security/lessecureapps
运行项目并检查收件人的邮件帐户。干杯!
另外,别忘了,在Android中,你不能通过任何活动进行网络操作。因此,建议使用
JAR文件:https://code.google.com/archive/p/javamail-android/
感谢您提供宝贵的信息。代码工作正常。我也可以通过添加以下代码来添加附件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private Multipart _multipart; _multipart = new MimeMultipart(); public void addAttachment(String filename,String subject) throws Exception { BodyPart messageBodyPart = new MimeBodyPart(); DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(filename); _multipart.addBodyPart(messageBodyPart); BodyPart messageBodyPart2 = new MimeBodyPart(); messageBodyPart2.setText(subject); _multipart.addBodyPart(messageBodyPart2); } message.setContent(_multipart); |
Could not connect to SMTP host:
smtp.gmail.com, port: 465
在清单中添加此行:
1 | <uses-permission android:name="android.permission.INTERNET" /> |
您可以使用JavaMail API来处理电子邮件任务。javamail API在javaee包中提供,其jar可供下载。遗憾的是,它不能直接在Android应用程序中使用,因为它使用的awt组件在Android中完全不兼容。
您可以在以下位置找到Javamail的Android端口:网址:http://code.google.com/p/javamail-android/
将JAR添加到应用程序并使用SMTP方法
为了帮助那些在主线程上获取网络异常,sdk目标>9。这是使用上面的Droopie代码,但对任何代码都是类似的。
1 2 3 4 5 | StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); android.os.NetworkOnMainThreadException |
您可以如下使用AsyncTask
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public void onClickMail(View view) { new SendEmailAsyncTask().execute(); } class SendEmailAsyncTask extends AsyncTask <Void, Void, Boolean> { Mail m = new Mail("[email protected]","my password"); public SendEmailAsyncTask() { if (BuildConfig.DEBUG) Log.v(SendEmailAsyncTask.class.getName(),"SendEmailAsyncTask()"); String[] toArr = {"to [email protected]"}; m.setTo(toArr); m.setFrom("from [email protected]"); m.setSubject("Email from Android"); m.setBody("body."); } @Override protected Boolean doInBackground(Void... params) { if (BuildConfig.DEBUG) Log.v(SendEmailAsyncTask.class.getName(),"doInBackground()"); try { m.send(); return true; } catch (AuthenticationFailedException e) { Log.e(SendEmailAsyncTask.class.getName(),"Bad account details"); e.printStackTrace(); return false; } catch (MessagingException e) { Log.e(SendEmailAsyncTask.class.getName(), m.getTo(null) +"failed"); e.printStackTrace(); return false; } catch (Exception e) { e.printStackTrace(); return false; } } |
SMTP
使用SMTP是一种可行的方法,其他人已经指出了如何做到这一点。请注意,在这样做的同时,您完全绕过了内置的邮件应用程序,您必须在代码中静态地提供SMTP服务器的地址、该服务器的用户名和密码,或者从用户那里查询。
超文本传输协议另一种方法是使用一个简单的服务器端脚本(如php),该脚本接受一些URL参数并使用它们发送邮件。这样,您只需要从设备发出HTTP请求(使用内置库很容易实现),而不需要在设备上存储SMTP登录数据。与直接使用smtp相比,这是另外一种间接方式,但是由于从php发出HTTP请求和发送邮件非常容易,所以它可能比直接方式更简单。
邮件应用程序如果邮件是从用户默认的邮件帐户发送的,而该帐户已经在电话中注册了,那么您必须采取其他方法。如果你有足够的时间和经验,你可能想检查Android电子邮件应用程序的源代码,看看它是否提供了一些入口点来发送没有用户交互的邮件(我不知道,但可能有一个)。
也许你甚至可以找到一种查询用户帐户详细信息的方法(这样你就可以将其用于SMTP),但我强烈怀疑这是可能的,因为这将是一个巨大的安全风险,并且安卓系统的构建相当安全。
100%带演示的工作代码,您也可以使用此答案发送多封电子邮件。
在此处下载项目
步骤1:下载邮件、激活、添加jar文件,并在Android Studio中添加到项目libs文件夹中。我添加了一个屏幕截图,见下面的下载链接
使用gmail登录(使用您的"从邮件"登录)并打开切换按钮链接
大多数人忘记了这一步,我希望你不会。
步骤2:完成此过程后。将这些类复制并传递到您的项目中。
爪哇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | import android.util.Log; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Properties; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; public class GMail { final String emailPort ="587";// gmail's smtp port final String smtpAuth ="true"; final String starttls ="true"; final String emailHost ="smtp.gmail.com"; String fromEmail; String fromPassword; List<String> toEmailList; String emailSubject; String emailBody; Properties emailProperties; Session mailSession; MimeMessage emailMessage; public GMail() { } public GMail(String fromEmail, String fromPassword, List<String> toEmailList, String emailSubject, String emailBody) { this.fromEmail = fromEmail; this.fromPassword = fromPassword; this.toEmailList = toEmailList; this.emailSubject = emailSubject; this.emailBody = emailBody; emailProperties = System.getProperties(); emailProperties.put("mail.smtp.port", emailPort); emailProperties.put("mail.smtp.auth", smtpAuth); emailProperties.put("mail.smtp.starttls.enable", starttls); Log.i("GMail","Mail server properties set."); } public MimeMessage createEmailMessage() throws AddressException, MessagingException, UnsupportedEncodingException { mailSession = Session.getDefaultInstance(emailProperties, null); emailMessage = new MimeMessage(mailSession); emailMessage.setFrom(new InternetAddress(fromEmail, fromEmail)); for (String toEmail : toEmailList) { Log.i("GMail","toEmail:" + toEmail); emailMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail)); } emailMessage.setSubject(emailSubject); emailMessage.setContent(emailBody,"text/html");// for a html email // emailMessage.setText(emailBody);// for a text email Log.i("GMail","Email Message created."); return emailMessage; } public void sendEmail() throws AddressException, MessagingException { Transport transport = mailSession.getTransport("smtp"); transport.connect(emailHost, fromEmail, fromPassword); Log.i("GMail","allrecipients:" + emailMessage.getAllRecipients()); transport.sendMessage(emailMessage, emailMessage.getAllRecipients()); transport.close(); Log.i("GMail","Email sent successfully."); } } |
发送邮件任务.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | import android.app.Activity; import android.app.ProgressDialog; import android.os.AsyncTask; import android.util.Log; import java.util.List; public class SendMailTask extends AsyncTask { private ProgressDialog statusDialog; private Activity sendMailActivity; public SendMailTask(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...."); GMail androidEmail = new GMail(args[0].toString(), args[1].toString(), (List) args[2], args[3].toString(), args[4].toString()); publishProgress("Preparing mail message...."); androidEmail.createEmailMessage(); publishProgress("Sending email...."); androidEmail.sendEmail(); 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(); } } |
步骤3:现在您可以根据需要更改这个类,也可以使用这个类发送多封邮件。我同时提供XML和Java文件。
活动u mail.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingLeft="20dp" android:paddingRight="20dp" android:paddingTop="30dp"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="10dp" android:text="From Email" /> <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFFFF" android:cursorVisible="true" android:editable="true" android:ems="10" android:enabled="true" android:inputType="textEmailAddress" android:padding="5dp" android:textColor="#000000"> <requestFocus /> </EditText> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="10dp" android:text="Password (For from email)" /> <EditText android:id="@+id/editText2" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFFFF" android:ems="10" android:inputType="textPassword" android:padding="5dp" android:textColor="#000000" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="10dp" android:text="To Email" /> <EditText android:id="@+id/editText3" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:ems="10" android:inputType="textEmailAddress" android:padding="5dp" android:textColor="#000000" /> <TextView android:id="@+id/textView4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="10dp" android:text="Subject" /> <EditText android:id="@+id/editText4" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:ems="10" android:padding="5dp" android:textColor="#000000" /> <TextView android:id="@+id/textView5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="10dp" android:text="Body" /> <EditText android:id="@+id/editText5" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:ems="10" android:inputType="textMultiLine" android:padding="35dp" android:textColor="#000000" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send Email" /> </LinearLayout> |
发送邮件活动.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import java.util.Arrays; import java.util.List; public class SendMailActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Button send = (Button) this.findViewById(R.id.button1); send.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Log.i("SendMailActivity","Send Button Clicked."); String fromEmail = ((TextView) findViewById(R.id.editText1)) .getText().toString(); String fromPassword = ((TextView) findViewById(R.id.editText2)) .getText().toString(); String toEmails = ((TextView) findViewById(R.id.editText3)) .getText().toString(); List<String> toEmailList = Arrays.asList(toEmails .split("\\s*,\\s*")); Log.i("SendMailActivity","To List:" + toEmailList); String emailSubject = ((TextView) findViewById(R.id.editText4)) .getText().toString(); String emailBody = ((TextView) findViewById(R.id.editText5)) .getText().toString(); new SendMailTask(SendMailActivity.this).execute(fromEmail, fromPassword, toEmailList, emailSubject, emailBody); } }); } } |
注意不要忘记在androidmanifest.xml文件中添加Internet权限
希望它能起作用,如果它不起作用,那就在下面评论一下。
这里有一个alt版本,它也适用于我,并且有附件(已经在上面发布了,但与源链接不同的是,源链接是完整的,人们发布了,因为它缺少数据,所以无法让它工作)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | 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 _user; private String _pass; 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 _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 Mail(String user, String pass) { this(); _user = user; _pass = pass; } public boolean send() throws Exception { Properties props = _setProperties(); if(!_user.equals("") && !_pass.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(_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 void setTo(String[] toArr) { // TODO Auto-generated method stub this._to=toArr; } public void setFrom(String string) { // TODO Auto-generated method stub this._from=string; } public void setSubject(String string) { // TODO Auto-generated method stub this._subject=string; } // more of the getters and setters ….. } |
在活动中调用它…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | @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() { public void onClick(View view) { Mail m = new Mail("[email protected]","password"); String[] toArr = {"[email protected]","[email protected]"}; m.setTo(toArr); m.setFrom("[email protected]"); m.setSubject("This is an email sent using my Mail JavaMail wrapper from an Android device."); m.setBody("Email body."); try { m.addAttachment("/sdcard/filelocation"); if(m.send()) { Toast.makeText(MailApp.this,"Email was sent successfully.", Toast.LENGTH_LONG).show(); } else { Toast.makeText(MailApp.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("MailApp","Could not send email", e); } } }); } |
如果使用"smtp.gmail.com"作为默认的smtp服务器,则发出警告。
谷歌会强迫你经常更改你的链接电子邮件帐户密码,因为他们过于热心的"可疑活动"政策。本质上,它将不同国家在短时间内重复发出的SMTP请求视为"可疑活动"。因为他们认为你(电子邮件帐户持有人)一次只能在一个国家。
当谷歌系统检测到"可疑活动"时,它将阻止更多的电子邮件,直到您更改密码。由于你已经将密码硬编码到应用程序中,所以每次发生这种情况时,你都必须重新发布应用程序,这并不理想。这在一周内发生了3次,我甚至把密码存储在另一台服务器上,每次谷歌强迫我更改密码时,我都会动态地获取密码。
因此,我建议使用许多免费的SMTP提供程序之一,而不是"smtp.gmail.com",以避免出现这种安全问题。使用相同的代码,但将"smtp.gmail.com"更改为新的smtp转发主机。
GmailBackground is small library to send an email in background without user interaction :
用途:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | BackgroundMail.newBuilder(this) .withUsername("[email protected]") .withPassword("password12345") .withMailto("[email protected]") .withType(BackgroundMail.TYPE_PLAIN) .withSubject("this is the subject") .withBody("this is the body") .withOnSuccessCallback(new BackgroundMail.OnSuccessCallback() { @Override public void onSuccess() { //do some magic } }) .withOnFailCallback(new BackgroundMail.OnFailCallback() { @Override public void onFail() { //do some magic } }) .send(); |
配置:
1 2 3 4 5 6 7 | repositories { // ... maven { url"https://jitpack.io" } } dependencies { compile 'com.github.yesidlazaro:GmailBackground:1.2.0' } |
权限:
1 2 | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> |
对于附件,还需要设置读取外部存储权限:
1 | <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> |
来源
(我自己测试过)
编辑:Javamail 1.5.5声称支持Android,所以你不需要其他任何东西。
<罢工>我把最新的Javamail(1.5.4)移植到了Android上。在Maven Central有售,只需在
1 | compile 'eu.ocathain.com.sun.mail:javax.mail:1.5.4' |
然后,您可以按照官方教程进行操作。
源代码可从以下网址获取:https://bitback.org/artbristol/javamail-forked-android
< /打击>
我为其他需要帮助的人找到了一个较短的选择。代码是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package com.example.mail; 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 SendMailTLS { public static void main(String[] args) { final String username ="[email protected]"; final String password ="password"; 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("username","password"); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress("[email protected]")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("[email protected]")); message.setSubject("Testing Subject"); message.setText("Dear Mail Crawler," +" No spam to my email, please!"); Transport.send(message); System.out.println("Done"); } catch (MessagingException e) { throw new RuntimeException(e); } } } |
来源:通过Javamail API发送电子邮件
希望这有帮助!祝你好运!
那些得到
发送带有附件的邮件…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | public class SendAttachment{ public static void main(String [] args){ //to address String to="[email protected]";//change accordingly //from address final String user="[email protected]";//change accordingly final String password="password";//change accordingly 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); //1) get the session object Properties properties = System.getProperties(); properties.put("mail.smtp.port","465"); properties.put("mail.smtp.host","smtp.gmail.com"); properties.put("mail.smtp.socketFactory.port","465"); properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); properties.put("mail.smtp.auth","true"); properties.put("mail.smtp.port","465"); Session session = Session.getDefaultInstance(properties, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user,password); } }); //2) compose message try{ MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(user)); message.addRecipient(Message.RecipientType.TO,new InternetAddress(to)); message.setSubject("Hii"); //3) create MimeBodyPart object and set your message content BodyPart messageBodyPart1 = new MimeBodyPart(); messageBodyPart1.setText("How is This"); //4) create new MimeBodyPart object and set DataHandler object to this object MimeBodyPart messageBodyPart2 = new MimeBodyPart(); //Location of file to be attached String filename = Environment.getExternalStorageDirectory().getPath()+"/R2832.zip";//change accordingly DataSource source = new FileDataSource(filename); messageBodyPart2.setDataHandler(new DataHandler(source)); messageBodyPart2.setFileName("Hello"); //5) create Multipart object and add MimeBodyPart objects to this object Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart1); multipart.addBodyPart(messageBodyPart2); //6) set the multiplart object to the message object message.setContent(multipart ); //7) send message Transport.send(message); System.out.println("MESSAGE SENT...."); }catch (MessagingException ex) {ex.printStackTrace();} } } |
我无法运行Vinayak B的代码。最后,我通过以下方式解决了这个问题:
1、使用此
2.应用异步任务。
3.更改发件人gmail帐户的安全问题。(更改为"打开")。
你考虑过使用ApacheCommons网络吗?从3.3开始,只需一个jar(并且您可以使用Gradle或Maven依赖它),就可以完成:http://blog.dahanne.net/2013/06/17/sending-a-mail-in-java-and-android-with-apache-commons-net/
无需用户干预,您可以按如下方式发送:
从客户端APK发送电子邮件。这里,May.jar,Actudio.Jar需要发送Java电子邮件。如果添加这些罐子,可能会增加APK大小。
或者,您可以在服务器端使用Web服务代码,该代码将使用相同的mail.jar和activation.jar来发送电子邮件。您可以通过AsyncTask调用Web服务并发送电子邮件。请参阅同一链接。
(但是,您需要知道邮件帐户的凭据)
如果需要尽可能保持JAR库的小,可以单独包含smtp/pop3/imap函数,以避免"dex中的方法太多"问题。
您可以从JavaNet网页中选择所需的JAR库,例如,mailapi.jar+imap.jar允许您以imap协议访问iCloud、hotmail邮件服务器。(在additional.jar和activation.jar的帮助下)
我尝试使用@vinayak b提交的代码。但是,我收到一个错误消息:没有用于SMTP的提供程序
我在这里创建了一个新问题,并提供了更多信息
毕竟我自己能修好。我不得不用另一封邮件.jar我必须确保我的"访问不太安全的应用程序"已打开。
我希望这能帮助任何有同样问题的人。完成后,这段代码也可以在Google Glass上工作。
其他答案中提供的所有代码都是正确的,并且工作正常,但是有点混乱,所以我决定发布一个库(尽管仍在开发中)以更简单的方式使用它:androidmail。
您只需创建一个邮件发送者,构建一个邮件并发送它(已经在后台用异步任务处理过)。
4您可以接收所发送电子邮件的通知,它还支持不同的收件人类型(收件人、抄送和密件抄送)、附件和HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | MailSender mailSender = new MailSender(email, password); Mail.MailBuilder builder = new Mail.MailBuilder(); Mail mail = builder .setSender(senderMail) .addRecipient(new Recipient(recipient)) .addRecipient(new Recipient(Recipient.TYPE.CC, recipientCC)) .setText("Hello") .setHtml("<h1 style="color:red;">Hello") .addAttachment(new Attachment(filePath, fileName)) .build(); mailSender.sendMail(mail, new MailSender.OnMailSentListener() { @Override public void onSuccess() { // mail sent! } @Override public void onError(Exception error) { // something bad happened :( } }); |
您可以通过Gradle或Maven获得:
1 | compile 'it.enricocandino:androidmail:1.0.0-SNAPSHOT' |
如果你有什么问题,请告诉我!:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | Add jar files mail.jar,activation.jar,additionnal.jar String sub="Thank you for your online registration" ; Mail m = new Mail("emailid","password"); String[] toArr = {"[email protected]",sEmailId}; m.setFrom("[email protected]"); m.setTo(toArr); m.setSubject(sub); m.setBody(msg); try{ if(m.send()) { } else { } } catch(Exception e) { Log.e("MailApp","Could not send email", e); } package com.example.ekktra; 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 _user; private String _pass; 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 _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 Mail(String user, String pass) { this(); _user = user; _pass = pass; } public boolean send() throws Exception { Properties props = _setProperties(); if(!_user.equals("") && !_pass.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(_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 void setTo(String[] toArr) { // TODO Auto-generated method stub this._to=toArr; } public void setFrom(String string) { // TODO Auto-generated method stub this._from=string; } public void setSubject(String string) { // TODO Auto-generated method stub this._subject=string; } } |
要添加附件,请不要忘记添加。
1 2 3 4 5 6 7 8 | 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); |