阿里邮件消息回执

之前使用阿里平台的短信和邮件发送服务,现在需要根据发送回执记录用户是否真实收到消息推送。查看文档发现可以通过消息服务MNS来实现,在此记录一下相关经验。

邮件消息回执

官方文档地址:https://help.aliyun.com/document_detail/52048.html

阿里云控制台配置:

开启MNS消息服务,

进入队列页面创建队列(接收回执消息使用)

进入主题页面创建主题,用于接收回执消息(阿里的消息回执是将回执消息推送到对应的主题,再通过订阅该主题的队列拉取回执消息,这里还需要注意一点,邮件的四个事件中,投递成功、投递失败是实时推送的,打开事件和点击事件是每个小时定时推送一次,队列才能拉取到该事件的消息,所以会出现延迟

创建事件通知规则(投递成功、投递失败、打开、点击,四种事件规则,事件通知之间规则不能重复

进入邮件推送服务,异步通知设置,我因为需要区分各环境之间消息,环境消息区分与短信回执相同只能自行在业务层面处理,所以我选择发信地址级异步通知,每个环境一个发信地址,通过回执消息中发信地址判断是否为当前环境消息。

关于发信地址级和账户级异步通知区别说明
1. 发信地址级异步通知优先级高于账户级异步通知。既设置账户级,又设置发信地址级异步通知,则账户级设置对该发信地址以外的其他发信地址生效。
2. 关闭发信地址级异步通知开关,则发信地址级和账户级异步通知对该发信地址都不生效。
3. 删除发信地址异步通知,则账号级设置对该发信地址生效。

拉取消息监听的代码可以参考短信回执的sdk-demo:https://help.aliyun.com/document_detail/101874.html

在编辑代码的时候有个问题需要注意一下:MNS消息接收的sdk中有两个jar包不能直接从maven中引入,需要自己手动处理一下,上传至自己maven仓库或者直接手动引入,具体的jar在demo中的lib中可以找到。需要注意一下,发送短信用的是:dysmsapi,MNS使用的是:dybaseapi。

alicom-mns-receive-sdk-1.0.1.jar

aliyun-java-sdk-dybaseapi-1.0.0.jar

因为只使用了接收消息回执,重写了demo中的DefaultAlicomMessagePuller类,线程池使用默认配置,其他根据自己实际情况配置

public void startEmailReciptListener(){

    logger.info("<<<<<<<<<<<<<<<<<<<<<<<<<<<<startEmailReciptListener:邮件消息回执监听启动>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

    EmailMessagePuller puller=new EmailMessagePuller();

    puller.setDebugLogOpen(emailOptionsProperties.getDebugLogOpen());

    String accessKeyId = "accessKeyId";//此处需要替换成开发者自己的AK信息
    String accessKeySecret="accessKeySecret";//此处需要替换成开发者自己的AK信息
    String mnsEndpoint="mnsEndpoint";//指定与ECS相同的地域
    String emailQueueName = "emailQueueName";//MNS平台上创建的队列名称

    puller.startReceiveMsg(accessKeyId,accessKeySecret,mnsEndpoint,emailQueueName,new EmailReceiptListener());

}

这里和短信回执有一点不同是,短信的队列是开启配置之后自动创建的,短信在实例化连接队列的时候需要向阿里进行请求认证,邮件的直接实例化获取队列就可以。

CloudAccount account = new CloudAccount(accessKeyId, accessKeySecret, mnsEndpoint);

MNSClient client = account.getMNSClient();

CloudQueue queue = client.getQueueRef(emailQueueName);

因为具体哪个环境的消息需要自己在业务层面中进行判断处理,之前针对不同环境分别创建了不同的发信地址,所有根据回执消息中的from字段进行区分(投递事件回执消息中account、from字段都是发件人地址,返回的信息都相同,没有区别,但是account只有投递事件中有)。这时候有一点需要注意:处理完消息后,是否将队列中的消息删除是根据处理结果返回的true/false进行判断的,如果返回false,消息会重新进入队列。所以我首先判断是否是当前环境消息,非本环境消息直接返回false,重新进入队列。(这里有一个问题,就是这条消息可能一直没被对应的环境拉取到,只能自行在代码层面进行幂等性处理。需要后期优化)。

static class EmailReceiptListener implements EmailMessageListener {
        @Override
        public boolean dealMailMessage(Message message) {
//            logger.info("<<<<<<<<<<<<<EmailReceiptListener:邮件消息回执messageId:"+message.getMessageId()+",处理开始:"+DateUtil.getCurrDate()+">>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            try{
                Map dealMap = dealMsgStr(message.getMessageBodyAsRawString());//自行处理回执消息,以”&”分隔key-val对,key-val对用”=”分隔
                //判断是否是当前环境消息
                if(dealMap.get("from").equals(emailAccount)){
                    switch (dealMap.get("event").toString()) {
                        case "deliver":
                            /**
                             * 回执消息中,err_code、err_msg为对方的收信服务器返回信息,不受阿里云控制
                             * failed_type为阿里云返回信息,枚举说明:https://help.aliyun.com/document_detail/52048.html?
                             * 投递消息只触发一次
                             */
                            break;
                        case "Click":
                            /**
                             * 点击事件会触发多次,如果邮件中有多个连接,或者相同连接点击多次,会多次发送回执消息,定时整点的时候统一推送
                             */
                            break;
                        case "Open":
                            /**
                             * 打开事件会触发多次,如果邮件打开多次,会多次发送回执消息,定时整点的时候统一推送
                             */
                            break;
                        default:
                            logger.error(dealMap.get("event").toString() + "=========事件不存在");
                    }
//                    logger.info(message.getMessageBodyAsRawString()+"====="+",处理结束:"+DateUtil.getCurrDate());
                }else{
//                    logger.info("<<<<<<<<<<<<<EmailReceiptListener:非当前环境消息回执:" + dealMap.get("from")+",处理结束:"+DateUtil.getCurrDate()+">>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                    return false;
                }
            } catch (Throwable e) {
                logger.error("处理邮件消息回执失败:"+message.getMessageBodyAsString()+e);
                return false;
            }
            //消息处理成功,返回true, SDK将调用MNS的delete方法将消息从队列中删除掉
            return true;
        }
    }

到这一步就成功接收到消息回执了,可以进行记录、重发等后续业务处理了。

仅以此记录成长,若是能提供帮助,再好不过了。

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值