在服务中发送电子邮件(不提示用户)

Posted

技术标签:

【中文标题】在服务中发送电子邮件(不提示用户)【英文标题】:Send Email in Service (without prompting user) 【发布时间】:2011-09-24 21:58:31 【问题描述】:

是否有可能我使用服务在后台发送电子邮件.. 就像在服务中我使用带有 ACTION_SENDTO 和 Uri 数据 mailto:recipient_email 的 Intent 并且它在没有任何用户干预的情况下在后台发送.. 或通过默认电子邮件应用程序而不提示用户...

【问题讨论】:

您想以编程方式发送电子邮件? 是,但使用用户配置的电子邮件而不是任何其他电子邮件 检查这些解决方案***.com/questions/4345032/…和***.com/questions/5456688/… 【参考方案1】:

最好的解决方案是使用 Gmail 帐户发送电子邮件。

一般来说:

    下载mail.jar和activation.jar for android https://code.google.com/p/javamail-android/ 连接到 GMail 以获取 OAuth 令牌 发送电子邮件

这是代码

import java.util.Properties;

import javax.activation.DataHandler;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.util.ByteArrayDataSource;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;

import com.sun.mail.smtp.SMTPTransport;
import com.sun.mail.util.BASE64EncoderStream;

public class GMailSender 
    private Session session;
    private String token;


    public String getToken() 
        return token;
    

    public GMailSender(Activity ctx) 
        super();
        initToken(ctx);
    

    public void initToken(Activity ctx) 

        AccountManager am = AccountManager.get(ctx);

        Account[] accounts = am.getAccountsByType("com.google");
        for (Account account : accounts) 
            Log.d("getToken", "account="+account);  
        

        Account me = accounts[0]; //You need to get a google account on the device, it changes if you have more than one


        am.getAuthToken(me, "oauth2:https://mail.google.com/", null, ctx, new AccountManagerCallback<Bundle>()
            @Override
            public void run(AccountManagerFuture<Bundle> result)
                try
                    Bundle bundle = result.getResult();
                    token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
                    Log.d("initToken callback", "token="+token);    

                 catch (Exception e)
                    Log.d("test", e.getMessage());
                
            
        , null);

        Log.d("getToken", "token="+token);
    



    public SMTPTransport connectToSmtp(String host, int port, String userEmail,
            String oauthToken, boolean debug) throws Exception 

        Properties props = new Properties();
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.starttls.required", "true");
        props.put("mail.smtp.sasl.enable", "false");

        session = Session.getInstance(props);
        session.setDebug(debug);

        final URLName unusedUrlName = null;
        SMTPTransport transport = new SMTPTransport(session, unusedUrlName);
        // If the password is non-null, SMTP tries to do AUTH LOGIN.
        final String emptyPassword = null;

        /* enable if you use this code on an Activity (just for test) or use the AsyncTask
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
         */

        transport.connect(host, port, userEmail, emptyPassword);

        byte[] response = String.format("user=%s\1auth=Bearer %s\1\1",
                userEmail, oauthToken).getBytes();
        response = BASE64EncoderStream.encode(response);

        transport.issueCommand("AUTH XOAUTH2 " + new String(response), 235);

        return transport;
    

    public synchronized void sendMail(String subject, String body, String user,
            String oauthToken, String recipients) 
        try 

            SMTPTransport smtpTransport = connectToSmtp("smtp.gmail.com", 587,
                    user, oauthToken, true);

            MimeMessage message = new MimeMessage(session);
            DataHandler handler = new DataHandler(new ByteArrayDataSource(
                    body.getBytes(), "text/plain"));
            message.setSender(new InternetAddress(user));
            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));
            smtpTransport.sendMessage(message, message.getAllRecipients());

         catch (Exception e) 
            Log.d("test", e.getMessage(), e);
        
    


此代码最初发布在这里 Javamail api in android using XOauth。

请注意,要获取 OAuth 令牌,您需要一个 Activity 并且您必须询问用户要使用哪个帐户。应在 OnCreate 阶段检索令牌并将其保存在首选项中。另见How to get the Android device's primary e-mail address

您也可以使用 mail.jar,但您必须询问用户的用户名和密码。

【讨论】:

您也可以从服务中获取 oauth 令牌,使用公共 AccountManagerFuture getAuthToken (Account account, String authTokenType, Bundle options, boolean notifyAuthFailure, AccountManagerCallback callback, Handler handler) @987654324 @ 你能告诉我,我从哪里获得这整个功能?我创建了 GmailSender 类并集成了谷歌登录,但我无法在后台发送邮件【参考方案2】:

使用 JavaMail API 在 Android 中使用 Gmail 身份验证发送电子邮件

创建示例项目的步骤:

MailSenderActivity.java

YOUR PACKAGE;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MailSenderActivity extends Activity 

    /** Called when the activity is first created. */
    @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) 
                // TODO Auto-generated method stub

                try    
                    GMailSender sender = new GMailSender("username@gmail.com", "password");
                    sender.sendMail("This is Subject",   
                            "This is Body",   
                            "user@gmail.com",   
                            "user@yahoo.com");   
                 catch (Exception e)    
                    Log.e("SendMail", e.getMessage(), e);   
                 

            
        );

    

GMailSender.java

YOUR PACKAGE;

import javax.activation.DataHandler;   
import javax.activation.DataSource;   
import javax.mail.Message;   
import javax.mail.PasswordAuthentication;   
import javax.mail.Session;   
import javax.mail.Transport;   
import javax.mail.internet.InternetAddress;   
import javax.mail.internet.MimeMessage;   
import java.io.ByteArrayInputStream;   
import java.io.IOException;   
import java.io.InputStream;   
import java.io.OutputStream;   
import java.security.Security;   
import java.util.Properties;   

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");   
           
       
  

JSSE 提供者

JSSEProvider.java

/*
 *  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 项目

mail.jar activation.jar additional.jar

Click here - How to add External Jars

别忘了在清单中添加这一行:

<uses-permission android:name="android.permission.INTERNET" />

运行项目并检查邮件的收件人邮件帐户。 干杯!!

希望对你有帮助

附:并且不要忘记您不能从 android 中的任何 Activity 进行网络操作。 因此建议使用AsyncTaskIntentService 以避免网络主线程异常。

Jar 文件:https://code.google.com/p/javamail-android/

【讨论】:

完美运行!使用 IntentService 但所有 .jar 链接都是 404\ 等待找到它code.google.com/archive/p/javamail-android/downloads【参考方案3】:

然后您需要以编程方式进行。这是 http://nilvec.com/sending-email-without-user-interaction-in-android/ Updated link using the Wayback Machine 的教程,因为该站点现在有一个域名抢注者

【讨论】:

好吧,我不想使用任何其他电子邮件或 java 库.. 使用用户配置的电子邮件发送它。 .. @waheed-khan 我不认为您可以使用内置的电子邮件应用程序在不提示用户的情况下发送电子邮件。但是您可能能够访问用户的电子邮件,然后将其与电子邮件 java 库一起使用来发送邮件。查看Accountmanger 以查看您是否可以访问帐户信息以找到所需的电子邮件地址。在此处找到示例:***.com/questions/2112965/…

以上是关于在服务中发送电子邮件(不提示用户)的主要内容,如果未能解决你的问题,请参考以下文章

在 Rails 中发送电子邮件通讯/调查

在 Obiee 中发送电子邮件

如何在 Java 中发送电子邮件?

如何根据新的安全策略在 .Net 中发送电子邮件?

如何根据新的安全策略在 .Net 中发送电子邮件?

php smtp 无法在 ubuntu 服务器中发送电子邮件