Unable to send email from google app engine

2019-09-18 18:08发布

问题:

I am on GAE Version 1.7.3 and using java mail api to send the email. On local development server the mail is sent fine. But after deploying to app engine i get following exception

com.google.apphosting.api.ApiProxy$CallNotFoundException: The API package 'remote_socket' or call 'Resolve()' was not found.
    at java.lang.Thread.getStackTrace(Thread.java:1495)
    at com.google.apphosting.runtime.ApiProxyImpl.doSyncCall(ApiProxyImpl.java:240)
    at com.google.apphosting.runtime.ApiProxyImpl.access$000(ApiProxyImpl.java:66)
    at com.google.apphosting.runtime.ApiProxyImpl$1.run(ApiProxyImpl.java:183)
    at com.google.apphosting.runtime.ApiProxyImpl$1.run(ApiProxyImpl.java:180)

    at java.security.AccessController.doPrivileged(Native Method)

    at com.google.apphosting.runtime.ApiProxyImpl.makeSyncCall(ApiProxyImpl.java:180)

    at com.google.apphosting.runtime.ApiProxyImpl.makeSyncCall(ApiProxyImpl.java:66)

    at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:107)
    at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:56)

    at com.google.appengine.api.socket.SocketApiHelper.apiProxyMakeSyncCall(SocketApiHelper.java:90)

    at com.google.appengine.api.socket.SocketApiHelper.makeSyncCall(SocketApiHelper.java:58)

    at com.google.appengine.api.socket.NameServiceImpl.lookupAllHostAddr(NameServiceImpl.java:61)

    at com.google.apphosting.util.ResolverManager$AppEngineNameservice.lookupAllHostAddr(ResolverManager.java:42)

    at java.net.InetAddress.getAddressFromNameService(InetAddress.java:1353)
    at java.net.InetAddress.getAllByName0(InetAddress.java:1303)

    at java.net.InetAddress.getAllByName(InetAddress.java:1232)

    at java.net.InetAddress.getAllByName(InetAddress.java:1163)

    at java.net.InetAddress.getByName(InetAddress.java:1113)

    at javax.mail.Service.connect(Service.java:257)

    at javax.mail.Service.connect(Service.java:91)

    at javax.mail.Service.connect(Service.java:76)

    at javax.mail.Transport.send(Transport.java:94)
    at javax.mail.Transport.send(Transport.java:48)
    at com.test.igreetings.service.impl.EmailImpl.sendEmail(EmailImpl.java:61)

Here is the my code to send the email:

try {
            // Email is my custom pojo class
            Email email = new Email();
            email.setMailHost("smtp.gmail.com");
            email.setAuth("true");
            email.setFrom("username@gmail.com");
            email.setTo("targetemail@example.com");
            email.setSubject("test);
            email.setMessage("test body");
            email.setPort("25");
            email.setStarttls("true");
            email.setLogin("username@gmail.com");
            email.setPassword("pwd");

            Properties props = new Properties();
            props.setProperty("mail.host", email.getMailHost());
            props.setProperty("mail.smtp.port", email.getPort());
            props.setProperty("mail.smtp.auth", email.getAuth());
            props.setProperty("mail.smtp.starttls.enable", email.getStarttls());

            Authenticator auth = new SMTPAuthenticator(email.getLogin(), email.getPassword());

            Session session = Session.getInstance(props, auth);

            MimeMessage msg = new MimeMessage(session);
            msg.setText(email.getMessage());
            msg.setSubject(email.getSubject());
            msg.setFrom(new InternetAddress(email.getFrom()));
            msg.addRecipient(Message.RecipientType.TO, new InternetAddress(email.getTo()));
            Transport transport = session.getTransport("smtp");
            transport.connect(email.getMailHost(), 25, "username@gmail.com", "pwd");

            transport.sendMessage(msg, msg.getAllRecipients());

            transport.close();
        } catch (AuthenticationFailedException ex) {
            Logging.log("AuthenticationFailedException in sendEmail: " + ex.toString());
            ex.printStackTrace();

        } catch (AddressException ex) {

            Logging.log("AddressException in sendEmail: " + ex.toString());
            ex.printStackTrace();
        } catch (MessagingException ex) {
            Logging.log("MessagingException in sendEmail: " + ex.toString());
            ex.printStackTrace();
        }

EDIT:

I have changed code per your suggestion and here is my updated code:

Properties props = new Properties();
                        Session session = Session.getDefaultInstance(props, null);
                        Message msg = new MimeMessage(session);
                        msg.setFrom(new InternetAddress("username@gmail.com"));
                        msg.addRecipient(Message.RecipientType.TO,
                        new InternetAddress("targetemail@example.com"));
                        msg.setSubject("test");
                        msg.setText("test");
                        Transport.send(msg);

And i am getting similar exception The API package 'remote_socket' or call 'CreateSocket()' was not found. The above sender is also registered as developer of this application.

回答1:

As @Shay noted you can not use external SMTP provider with GAE. GAE uses it's own SMTP gateway.

Related issue: on GAE you can only send email that originates (i.e. from field) from one of the app administrators (GAE Admin -> permissions) or currently logged-in users via Google Accounts. Note: this only works for users logged-in via Google Accounts, not for users logged in via federated login (e.g. OpenID): Sending email on behalf of Google Apps user (answer is from Google engineer)

Update: as noted before, the username@gmail.com must be the email of the user that logged into your GAE app via Google Apps login or the user must be an admin of your GAE app.

Update2: this works for me:

Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
try {
    Message msg = new MimeMessage(session);
    msg.setFrom(new InternetAddress("admin@domain.com", "Admin", "UTF-8"));
    msg.addRecipient(Message.RecipientType.TO, new InternetAddress(recipientAddress));
    msg.setSubject(emailSubject);
    msg.setText(emailText);
    Transport.send(msg);

} catch (AddressException e) {
// TO address not valid
} catch (MessagingException e) {
    // other email error
} catch (UnsupportedEncodingException e) {
    // should not happen UTF-8 is always available
}


回答2:

An app cannot use the JavaMail interface to connect to other mail services for sending or receiving email messages. SMTP configuration added to the Transport or Session is ignored.

Remove the port, user, password and mail host settings, and it should work.