分享一下在springboot中整合rabbitmq来发送邮件,这一玩也是玩了两小时,一步一个坑。。。关于rabbitmq的介绍就不说,先引入依赖
org.springframework.boot
spring-boot-starter-mail
org.springframework.boot
spring-boot-starter-amqp
1.5.2.RELEASE
org.springframework.boot
spring-boot-starter-logging
配置文件:
配置文件:
#对于rabbitMQ的支持
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#邮件配置
#服务器邮箱地址
spring.mail.host=smtp.163.com
#端口
spring.mail.port=587
#发邮件的邮箱(我用了自己的)
[email protected]
#服务认证密码(并不是你的邮箱登录密码)
spring.mail.password=xxx
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.ssl.enable=true
这里说一下坑一开始在网上找了资料spring.mail.host用的是smtp.qiye.163.com,就一直报这个错,还有一开始以为密码就是自己的登录密码
Caused by: javax.mail.MessagingException: Could not connect to SMTP host: smtp.qiye.163.com, port: 587
顺便说一下如何获取服务认证密码和找到正确的服务器邮箱地址,其实只要登陆你的163邮箱到设置选择POP3/SMTP/IMAP将服务启动,会让你发几条短信,之后就会有认证密码给你,记得保存
当你完成了这一切时你以为完事了,结果发现还是报错,那是因为你没设置ssl连接方式spring.mail.properties.mail.smtp.ssl.enable=true
Caused by: javax.mail.MessagingException: Could not connect to SMTP host: smtp.163.com, port: 587, response: -1
这些都弄完了基本上就整合完了,稍微来写一点代码:
rabbitmq配置类:
/**
* Broker:它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式进行传输,
* Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
* Queue:消息的载体,每个消息都会被投到一个或多个队列。
* Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来.
* Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
* vhost:虚拟主机,一个broker里可以有多个vhost,用作不同用户的权限分离。
* Producer:消息生产者,就是投递消息的程序.
* Consumer:消息消费者,就是接受消息的程序.
* Channel:消息通道,在客户端的每个连接里,可建立多个channel.
*/
@Configuration
public class RabbitConfiguration {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Value("${spring.rabbitmq.host}")
private String host;
@Value("${spring.rabbitmq.port}")
private int port;
@Value("${spring.rabbitmq.username}")
private String username;
@Value("${spring.rabbitmq.password}")
private String password;
//交换机
public static final String EXCHANGE_A = "my-mq-exchange_A";
public static final String EXCHANGE_B = "my-mq-exchange_B";
public static final String EXCHANGE_C = "my-mq-exchange_C";
//消息队列
public static final String QUEUE_A = "QUEUE_A";
public static final String QUEUE_B = "QUEUE_B";
public static final String QUEUE_C = "QUEUE_C";
//路由键
public static final String ROUTINGKEY_A = "spring-boot-routingKey_A";
public static final String ROUTINGKEY_B = "spring-boot-routingKey_B";
public static final String ROUTINGKEY_C = "spring-boot-routingKey_C";
/**
* 建立连接
* @return
*/
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host,port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost("/");
connectionFactory.setPublisherConfirms(true);
return connectionFactory;
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
//必须是prototype类型
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
template.setEncoding("UTF-8");
template.setMandatory(true);
return template;
}
/**
* 针对消费者配置
* 1. 设置交换机类型
* 2. 将队列绑定到交换机
FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
HeadersExchange :通过添加属性key-value匹配
DirectExchange:按照routingkey分发到指定队列
TopicExchange:多关键字匹配
*/
@Bean
public DirectExchange defaultExchange() {
return new DirectExchange(EXCHANGE_A);
}
/**
* 获取队列A
* @return
*/
@Bean
public Queue queueA() {
return new Queue(QUEUE_A, true); //队列持久
}
/**
* 获取队列B
* @return
*/
@Bean
public Queue queueB() {
return new Queue(QUEUE_B, true); //队列持久
}
/**
* 一个交换机可以绑定多个消息队列,也就是消息通过一个交换机,可以分发到不同的队列当中去
* @return
*/
@Bean
public Binding bindingA() {
return BindingBuilder.bind(queueA()).to(defaultExchange()).with(RabbitConfiguration.ROUTINGKEY_A);
}
@Bean
public Binding bindingB() {
return BindingBuilder.bind(queueB()).to(defaultExchange()).with(RabbitConfiguration.ROUTINGKEY_B);
}
构造一个邮件实体:
public class MailBean {
/**
* 邮件主题
*/
private String subject;
/**
* 邮件内容
*/
private String text;
/**
* 附件
*/
private FileSystemResource file;
/**
* 附件名称
*/
private String attachmentFilename;
/**
* 内容ID,用于发送静态资源邮件时使用
*/
private String contentId;
//省略get和set方法
}
邮件工具类:
@Component
public class MailUtil {
@Autowired
private JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String sender;
//要发送到的邮箱
private final static String TO_MAIL_ADDR = "[email protected]";
/**
* 发送邮件测试方法
*/
public void sendMail() {
SimpleMailMessage mimeMessage = new SimpleMailMessage();
mimeMessage.setFrom(sender);
mimeMessage.setTo(TO_MAIL_ADDR);
mimeMessage.setSubject("SpringBoot集成JavaMail实现邮件发送");
mimeMessage.setText("SpringBoot集成JavaMail实现邮件发送正文");
mailSender.send(mimeMessage);
}
/**
* 发送简易邮件
* @param MailBean
*/
public void sendMail(MailBean MailBean) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);
try {
helper.setFrom(sender);
helper.setTo(TO_MAIL_ADDR);
helper.setSubject(MailBean.getSubject());
helper.setText(MailBean.getText());
} catch (MessagingException e) {
e.printStackTrace();
}
mailSender.send(mimeMessage);
}
/**
* 发送邮件-邮件正文是HTML
* @param MailBean
*/
public void sendMailHtml(MailBean MailBean) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);
try {
helper.setFrom(sender);
helper.setTo(TO_MAIL_ADDR);
helper.setSubject(MailBean.getSubject());
helper.setText(MailBean.getText(), true);
} catch (MessagingException e) {
e.printStackTrace();
}
mailSender.send(mimeMessage);
}
/**
* 发送邮件-附件邮件
* @param MailBean
*/
public void sendMailAttachment(MailBean MailBean) {
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(sender);
helper.setTo(TO_MAIL_ADDR);
helper.setSubject(MailBean.getSubject());
helper.setText(MailBean.getText(), true);
// 增加附件名称和附件
helper.addAttachment(MailBean.getAttachmentFilename(), MailBean.getFile());
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}
/**
* 内联资源(静态资源)邮件发送
* 由于邮件服务商不同,可能有些邮件并不支持内联资源的展示
* 在测试过程中,新浪邮件不支持,QQ邮件支持
* 不支持不意味着邮件发送不成功,而且内联资源在邮箱内无法正确加载
* @param MailBean
*/
public void sendMailInline(MailBean MailBean) {
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(sender);
helper.setTo(TO_MAIL_ADDR);
helper.setSubject(MailBean.getSubject());
/*
* 内联资源邮件需要确保先设置邮件正文,再设置内联资源相关信息
*/
helper.setText(MailBean.getText(), true);
helper.addInline(MailBean.getContentId(), MailBean.getFile());
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}
/**
* 模板邮件发送
* @param MailBean
*/
public void sendMailTemplate(MailBean MailBean) {
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(sender);
helper.setTo(TO_MAIL_ADDR);
helper.setSubject(MailBean.getSubject());
helper.setText(MailBean.getText(), true);
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
service和service实现类:
public interface MailService {
/**
* 推送消息并发送邮件
* @param msg
* @return
*/
String sendMsgToMq(String msg);
}
@Service
public class MailServiceImpl implements MailService {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private MailUtil mailUtil;
@Override
public String sendMsgToMq(String msg) {
//消息生产
rabbitTemplate.convertAndSend(RabbitConfiguration.EXCHANGE_A, RabbitConfiguration.ROUTINGKEY_B, msg);
logger.info("rabbitmq消息已经发送到交换机, 等待交换机接收..." + msg);
return "success";
}
@RabbitListener(queues = RabbitConfiguration.QUEUE_B)
private void sendEMail(String msg){
MailBean mailBean = new MailBean();
mailBean.setSubject("极限云上线测试");
mailBean.setText(msg);
//发送邮件
mailUtil.sendMail(mailBean);
logger.info("已发送邮件");
}
}
controller层:ResponseVo这个自定义响应类就不贴出来了,在之前的springboot的全局异常处理文章中有贴出来过
@Api(tags = {"邮件管理"})
@RestController
@RequestMapping("/email")
public class MailController {
@Autowired
private MailService mailServiceImpl;
/**
* 发送一条消息
* @param msg
* @return
*/
@ApiOperation(value="发送一条消息")
@RequestMapping(value = "/sendMsg", method = RequestMethod.POST)
public ResponseVo findUserByUserName(@RequestBody @ApiParam String msg) {
String s = mailServiceImpl.sendMsgToMq(msg);
return ResponseVo.success(s);
}
}