无需密码发送电子邮件

4
我正在开发一款安卓应用。在我的应用中,我有一个反馈表单。我要求用户输入电子邮件地址作为输入。当用户点击提交按钮时,我希望该电子邮件能够发送,而不需要用户添加密码。
我已经检查了使用Intent的默认方法以及下面链接中的第二种方法... 第二种方法

我在我的应用程序中不得不做类似这样的事情... @Hajjat的答案的一个大问题是它打开了大量可能的应用程序。我使用的解决方案是要求他们提供电子邮件,然后让应用程序发送一个HTTP请求(带有电子邮件和他们的反馈),发送到我制作的页面,然后让该页面使用提供的电子邮件发送电子邮件。 - Joseph Boyle
3个回答

6
如果您希望电子邮件由应用程序用户的帐户发送,需要适当的身份验证。
因此,您可以向邮件应用程序发送意图(如您所述),或者自己进行操作(如您提到的第二种方法)。
但是,显然第二种方法需要密码,因为您正在代表用户发送电子邮件(从他们的帐户中)。 Gmail(或事实上任何邮件服务提供商)不会在没有密码的情况下允许这样做。
简而言之,不能在没有密码的情况下执行此操作。
相反,您可以使用解决方法。您可以通过单个邮件ID(由您创建,因此您知道密码)发送应用程序发送的所有电子邮件。现在,在电子邮件内容中,您可以存储要求反馈的用户的电子邮件ID。
这样,您只需要求邮件ID(无需密码),如果需要联系他们,则还可以获得他们的联系信息。
希望能对您有所帮助。
祝你好运。

嘿,如果我想配置一些公司电子邮件地址,比如xyz@abc.com,如果我更改SMTP客户端和所有内容,第二种方法是否有效? - Riddhi Shah
是的,它会。第二种方法适用于任何SMTP客户端(只要API可用),因为您对帐户拥有完全的访问控制。因此,它肯定适用于公司电子邮件。 - Tanmay Patil
你好。嘿,我配置了我的公司电子邮件地址并设置了SMTP,但我无法通过我的Android应用程序发送电子邮件。我遇到了这个错误javax.mail.MessagingException:无法连接到SMTP主机:mail.kunjinc.org,端口:465; 嵌套异常是:javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:找不到认证路径的信任锚点。即使我尝试更改端口号,我仍然无法发送电子邮件。 - Riddhi Shah
抱歉回复晚了。这个链接可能会对你有所帮助。http://developer.android.com/training/articles/security-ssl.html#HttpsExample 如果问题仍然存在,最好发布另一个带有代码的问题。祝你好运。 - Tanmay Patil

2

我曾经有同样的问题,并找到了一种解决方案,我对其进行了修改以使其适用于我。你可以在堆栈溢出中搜索,但我使用的解决方案来自发送邮件而不使用默认设置我的令牌是在电子邮件发送后检索的。无论如何,这里是我创建的一个工作示例的片段。

  1. I imported the following jars:
    compile files('libs/activation.jar') compile files('libs/additionnal.jar') compile files('libs/mail.jar')

  2. I had the following permission requests <uses-permission android:name="android.permission.GET_ACCOUNTS"> </uses-permission> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"> </uses-permission> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.USE_CREDENTIALS"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

  3. Also for my scenario I asked the user for their user account. If you know it then you can skip this step. the snippet I have for this can be done another way using helper methods provided by studio libs however I just did it via a dialog.

    public Account[] getGoogleAccounts(){ return accounts = acctManager.getAccountsByType("com.google"); }

    public void getGoogleAccountsDialog(){
    if( getGoogleAccounts().length>1) {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setTitle("Select Google Account:")
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                })
                .setItems(convertAccountTo(getGoogleAccounts()), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        setSelectedAcct(accounts[which]);
                        initToken(activity);
                        dialog.dismiss();
                    }
                });
        builder.create();
        builder.show();
    }
    else if(getGoogleAccounts().length==1){
        setSelectedAcct(getGoogleAccounts()[0]);
    }
    else{
        Toast.makeText(context,"No google account(s) exists on this device.",Toast.LENGTH_LONG);
    }
    

    }'

  4. because this is a working sample i just have dummy text setup to fire the email immediately after the name is selected. However you will modify this code for you suiting.

获得令牌后,我发送电子邮件请求,其中包含getAndUseAuthTokenInAsynTask()。

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

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

}
  1. lastly the remainder of the calls

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

    }

    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;
    
    transport.connect(host, port, userEmail, emptyPassword);
    
    byte[] response = String.format("user=%s\1auth=Bearer %s\1\1",
            userEmail, token).getBytes();
    response = BASE64EncoderStream.encode(response);
    
    transport.issueCommand("AUTH XOAUTH2 " + new String(response), 235);
    
    return transport;
    

    }

希望这能帮到其他人。请记住,发送邮件不应在主线程上执行。


0

不确定对您是否有用,但您是否考虑过使用内置的电子邮件功能?这甚至不需要用户输入他们的用户ID或密码,但当然他们会离开您的应用程序到电子邮件客户端发送电子邮件。

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
String[] recipients = new String[]{"recipient@email.com", "",};
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, recipients);
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Sample mail");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "This is a sample mail..");
emailIntent.setType("text/plain");
startActivity(Intent.createChooser(emailIntent, "Send mail client :"));

(顺便说一句:这将显示许多其他应用程序,包括电子邮件客户端。如果您对这样的解决方案感兴趣,我可以发布一些代码来过滤除所有应用程序,但保留电子邮件客户端)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接