我正在尝试使用Java发送电子邮件:
import java.util.*; import javax.mail.*; import javax.mail.internet.*; import javax.activation.*; public class SendEmail { public static void main(String [] args) { // Recipient's email ID needs to be mentioned. String to = "abcd@gmail.com"; // Sender's email ID needs to be mentioned String from = "web@gmail.com"; // Assuming you are sending email from localhost String host = "localhost"; // Get system properties Properties properties = System.getProperties(); // Setup mail server properties.setProperty("mail.smtp.host", host); // Get the default Session object. Session session = Session.getDefaultInstance(properties); try{ // Create a default MimeMessage object. MimeMessage message = new MimeMessage(session); // Set From: header field of the header. message.setFrom(new InternetAddress(from)); // Set To: header field of the header. message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // Set Subject: header field message.setSubject("This is the Subject Line!"); // Now set the actual message message.setText("This is actual message"); // Send message Transport.send(message); System.out.println("Sent message successfully...."); }catch (MessagingException mex) { mex.printStackTrace(); } } }
我收到错误消息:
javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25; nested exception is:java.net.ConnectException: Connection refused: connect at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1706) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:525)
此代码可以发送电子邮件吗?
户名+密码不再是推荐的解决方案。这是因为
我尝试了此操作,Gmail向该代码中用作用户名的电子邮件发送了一封电子邮件,其中说我们最近阻止了你的Google帐户的登录尝试,并将我定向到此支持页面:support.google.com/accounts/answer/6010255因此它看起来很有效,用于发送邮件的电子邮件帐户需要降低自身的安全性
Google已发布Gmail API- https://developers.google.com/gmail/api/?hl= zh- CN。我们应该使用oAuth2方法,而不是用户名+密码。
这是与Gmail API配合使用的代码段。
GoogleMail.java import com.google.api.client.util.Base64; import com.google.api.services.gmail.Gmail; import com.google.api.services.gmail.model.Message; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Properties; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; /** * * @author doraemon */ public class GoogleMail { private GoogleMail() { } private static MimeMessage createEmail(String to, String cc, String from, String subject, String bodyText) throws MessagingException { Properties props = new Properties(); Session session = Session.getDefaultInstance(props, null); MimeMessage email = new MimeMessage(session); InternetAddress tAddress = new InternetAddress(to); InternetAddress cAddress = cc.isEmpty() ? null : new InternetAddress(cc); InternetAddress fAddress = new InternetAddress(from); email.setFrom(fAddress); if (cAddress != null) { email.addRecipient(javax.mail.Message.RecipientType.CC, cAddress); } email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress); email.setSubject(subject); email.setText(bodyText); return email; } private static Message createMessageWithEmail(MimeMessage email) throws MessagingException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); email.writeTo(baos); String encodedEmail = Base64.encodeBase64URLSafeString(baos.toByteArray()); Message message = new Message(); message.setRaw(encodedEmail); return message; } public static void Send(Gmail service, String recipientEmail, String ccEmail, String fromEmail, String title, String message) throws IOException, MessagingException { Message m = createMessageWithEmail(createEmail(recipientEmail, ccEmail, fromEmail, title, message)); service.users().messages().send("me", m).execute(); } }
要通过oAuth2构建授权的Gmail服务,请使用以下代码段。
实用工具
import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.gson.GsonFactory; import com.google.api.client.util.store.FileDataStoreFactory; import com.google.api.services.gmail.Gmail; import com.google.api.services.gmail.GmailScopes; import com.google.api.services.oauth2.Oauth2; import com.google.api.services.oauth2.model.Userinfoplus; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.file.Files; import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.util.HashSet; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.yccheok.jstock.engine.Pair; /** * * @author yccheok */ public class Utils { /** Global instance of the JSON factory. */ private static final GsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance(); /** Global instance of the HTTP transport. */ private static HttpTransport httpTransport; private static final Log log = LogFactory.getLog(Utils.class); static { try { // initialize the transport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); } catch (IOException ex) { log.error(null, ex); } catch (GeneralSecurityException ex) { log.error(null, ex); } } private static File getGmailDataDirectory() { return new File(org.yccheok.jstock.gui.Utils.getUserDataDirectory() + "authentication" + File.separator + "gmail"); } /** * Send a request to the UserInfo API to retrieve the user's information. * * @param credentials OAuth 2.0 credentials to authorize the request. * @return User's information. * @throws java.io.IOException */ public static Userinfoplus getUserInfo(Credential credentials) throws IOException { Oauth2 userInfoService = new Oauth2.Builder(httpTransport, JSON_FACTORY, credentials).setApplicationName("JStock").build(); Userinfoplus userInfo = userInfoService.userinfo().get().execute(); return userInfo; } public static String loadEmail(File dataStoreDirectory) { File file = new File(dataStoreDirectory, "email"); try { return new String(Files.readAllBytes(Paths.get(file.toURI())), "UTF-8"); } catch (IOException ex) { log.error(null, ex); return null; } } public static boolean saveEmail(File dataStoreDirectory, String email) { File file = new File(dataStoreDirectory, "email"); try { //If the constructor throws an exception, the finally block will NOT execute BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")); try { writer.write(email); } finally { writer.close(); } return true; } catch (IOException ex){ log.error(null, ex); return false; } } public static void logoutGmail() { File credential = new File(getGmailDataDirectory(), "StoredCredential"); File email = new File(getGmailDataDirectory(), "email"); credential.delete(); email.delete(); } public static Pair<Pair<Credential, String>, Boolean> authorizeGmail() throws Exception { // Ask for only the permissions you need. Asking for more permissions will // reduce the number of users who finish the process for giving you access // to their accounts. It will also increase the amount of effort you will // have to spend explaining to users what you are doing with their data. // Here we are listing all of the available scopes. You should remove scopes // that you are not actually using. Set<String> scopes = new HashSet<>(); // We would like to display what email this credential associated to. scopes.add("email"); scopes.add(GmailScopes.GMAIL_SEND); // load client secrets GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(Utils.JSON_FACTORY, new InputStreamReader(Utils.class.getResourceAsStream("/assets/authentication/gmail/client_secrets.json"))); return authorize(clientSecrets, scopes, getGmailDataDirectory()); } /** Authorizes the installed application to access user's protected data. * @return * @throws java.lang.Exception */ private static Pair<Pair<Credential, String>, Boolean> authorize(GoogleClientSecrets clientSecrets, Set<String> scopes, File dataStoreDirectory) throws Exception { // Set up authorization code flow. GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( httpTransport, JSON_FACTORY, clientSecrets, scopes) .setDataStoreFactory(new FileDataStoreFactory(dataStoreDirectory)) .build(); // authorize return new MyAuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user"); } public static Gmail getGmail(Credential credential) { Gmail service = new Gmail.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName("JStock").build(); return service; } }