Java发邮件gmail

前言

        由于项目打算在运行,采用了谷歌邮箱来发邮件给别人激活绑定,因此用到了gmail

Java发送邮件

        这个没啥好说的,参考网上文档就行了,很多文章,这里放几篇参考

java实现发邮件功能的三种方式_wx64c2275ec6e2d的技术博客_51CTO博客

047-Java 发送邮件-CSDN博客

gmail配置

百度安全验证 ,  不过imap 从 2025 年1月1号就默认开启了,所以配不配都无所谓

特殊的时gmail 不支持直接用邮箱密码来进行Java调用,比如你的邮箱密码如下

xxx.@gmail.com /  123456  

直接用这个去调用去没办法访问,会报  535-5.7.8 Username and Password not accepted 错误

这个问题有两种解决方案

1 . 把安全性降低: https://myaccount.google.com/lesssecureapps 去这个地址把支持不安全的请求开关打开,但是有些账号是不支持关的,比如我的,所以我用的是第二种方式

2.1. 添加两步认证, https://myaccount.google.com/u/0/security  到这里找到两步认证,然后把它打开,需要输入备用手机号

2.2  如果你已经打开了直接来这一步即可,到 https://myaccount.google.com/apppasswords设置专用的应用密码,如下所示

应用专用密码

接着输入应用名称,然后点击生成即可,然后会生成一个16位的字符串给你,你拿这个密码去请求就可以正常发邮件了,注意空格要去掉

看它这里的设计应该是同个密码都可以使用的,但是你如果不同应用也是可以创建多个应用的,密码记得自己保存好,这里没有展示

注意这个链接是隐藏的,我找了好久才找到

扩展

        发送邮件的邮箱可能有几种类型的,这里也可以考虑做个设计模式,抽象一个发送邮箱的接口出来,然后提供不同的实现,哪个发不出去的时候可以用哪个发送一下

        

        发邮件这个东西最好用异步发送,因为时间还是比较久的

        

        发送失败的超时时间最好也设置一下,别到时因为这个功能引起系统的崩溃,设置个5秒内发不成功就退出好了,然后打印日志一般,也可以发到告警平台里面去进行人工介入处理, 参考: Java 邮件发送超时时间问题及优化方案详解!-腾讯云开发者社区-腾讯云

设计模式

        还是采用了设计模式,这里就直接贴结构图和代码,也可以做个参考

代码如下,其实并不复杂,设计模式就是这样,第一次没意义,后面第二次就有意义了

@Slf4j
@Component
public abstract class AbstractEmailSender {


    public static final String GMAIL_SOURCE = "gmail_source";
    public static final String TENCENT_ENTERPRISE_SOURCE = "tencent_enterprise_source";

    @Resource
    private MessageSourceComponent messageSourceComponent;

    public void sendGmailActivationCode(String toUser, Object code) {

        log.info("sendGmailActivationCode给用户发送激活码,用户为{},激活码为{}", toUser, code);

        String subject = messageSourceComponent.getMessage(OverSeaErrorConst.EMAIL_SUBJECT);
        String content = messageSourceComponent.getMessage(OverSeaErrorConst.EMAIL_CONTENT, new Object[]{code});

        sendGmail(new EmailSendBo(toUser, subject, content));
    }

    public void sendGmail(EmailSendBo emailSendBo) {


        String source = getSource();
        EmailCoreBo emailCoreBo = getEmailCoreBo();

        Properties properties = new Properties();

        //设置proper信息
        doSendEmailProperTits(properties);

        // 设置超时参数
        properties.put("mail.smtp.connectiontimeout", "5000"); // 连接超时,单位为毫秒
        properties.put("mail.smtp.timeout", "5000"); // 读超时
        properties.put("mail.smtp.writetimeout", "5000"); // 写超时

        // 获取会话对象
        Session session = Session.getInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(emailCoreBo.getUserName(), emailCoreBo.getPassword());
            }
        });

        try {
            // 创建邮件消息
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(emailCoreBo.getUserName()));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(emailSendBo.getToUser()));
            message.setSubject(emailSendBo.getSubject());
            message.setText(emailSendBo.getContent());

            log.info("发送sendGmail邮箱数据,来源{}", source);
            // 发送邮件
            Transport.send(message);
            log.info("发送sendGmail邮箱成功,来源{}", source);

        } catch (MessagingException e) {
            log.error("发送sendGmail邮箱失败,来源{}", source, e);
        }
    }

    protected abstract void doSendEmailProperTits(Properties properties);

    protected abstract EmailCoreBo getEmailCoreBo();

    protected abstract String getSource();
@Slf4j
@Component
public class GmailEmailSender extends AbstractEmailSender {

    //gmail邮箱相关配置-其实可以专门搞个类,但是目前先不弄了,知道这回事就行
    private static final String GMAIL_HOST = "smtp.gmail.com";
    private static final String GMAIL_USER = "xxx@gmail.com";
    private static final String GMAIL_PORT = "587";
    private static final String GMAIL_PASSWORD = "xxxxxxxxx"; //应用专用密码

    @Override
    public void doSendEmailProperTits(Properties properties) {
        properties.put("mail.smtp.host", GMAIL_HOST);
        properties.put("mail.smtp.port", GMAIL_PORT);
        properties.put("mail.smtp.auth", "true");
        properties.put("mail.smtp.starttls.enable", "true"); // 启用 STARTTLS
    }

    @Override
    public EmailCoreBo getEmailCoreBo() {
        return new EmailCoreBo(GMAIL_USER, GMAIL_PASSWORD);
    }

    @Override
    public String getSource() {
        return AbstractEmailSender.GMAIL_SOURCE;
    }
@Component
public class EmailSenderContext {

    @Resource
    private List<AbstractEmailSender> emailSenderList;

    public AbstractEmailSender defaultEmailSender() {
        return getEmailSender(AbstractEmailSender.GMAIL_SOURCE);
    }

    public AbstractEmailSender getEmailSender(String source) {
        for (AbstractEmailSender abstractEmailSender : emailSenderList) {
            if(Objects.equals(source, abstractEmailSender.getSource())) {
                return abstractEmailSender;
            }
        }
        throw new AppException(ErrorCode.SYS_ERROR.code(), "not found emailSender");
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmailCoreBo {

    private String userName;

    private String password;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmailSendBo {

    private String toUser;

    private String subject;

    private String content;
}
@Slf4j
@Component
public class TencentEnterpriseEmailSender extends AbstractEmailSender {

    //腾讯企业邮箱邮箱相关配置
    private static final String TENCENT_HOST = "smtp.exmail.qq.com";
    private static final String TENCENT_PORT = "465";
    private static final String TENCENT_USER = "ff@11.cn";
    private static final String TENCENT_PASSWORD = "23232322"; //应用专用密码

    @Override
    public void doSendEmailProperTits(Properties properties) {
        properties.put("mail.smtp.host", TENCENT_HOST);
        properties.put("mail.smtp.port", TENCENT_PORT);
//        properties.put("mail.smtp.auth", "true");
//        properties.put("mail.smtp.starttls.enable", "true"); // 启用 STARTTLS
    }

    @Override
    public EmailCoreBo getEmailCoreBo() {
        return new EmailCoreBo(TENCENT_USER, TENCENT_PASSWORD);
    }

    @Override
    public String getSource() {
        return AbstractEmailSender.TENCENT_ENTERPRISE_SOURCE;
    }
}

总结

        其实代码反而简单,毕竟有别人整理好的,主要是gmail的二步认证是个新鲜的东西,以前很少开发海外的东西,这次就当做下简单的整理

注意

1. 本地就算开了vpn好像也过不去,会报错,可能是vpn配置问题,所以你最好有个海外的服务器看才是最准的,但是其实你是能过去的

Got bad greeting from SMTP host: smtp.gmail.com, port: 587, response: [EOF]

2. 要使用二次验证专用密码,否则直接用邮箱密码可能过不去

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值