【异常】SpringBoot集成Outlook报错The remote server returned an error: (401)Unauthorized

本文介绍了在SpringBoot项目中集成Outlook发送邮件时遇到的401 Unauthorized错误,详细分析了从Service实现类、发邮件组件到发邮件工具类的错误定位过程,并最终发现是由于账号密码有效期问题导致。解决方案是更新为长期有效的账号密码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、报错内容

logdate: 2023-03-14 16:50:00.782
loglevel: ERROR
logmessage: sendMailByIoIntegral error:{}
microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException: The request failed. The request failed. The remote server returned an error: (401)Unauthorized
	at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:74)
	at microsoft.exchange.webservices.data.core.request.MultiResponseServiceRequest.execute(MultiResponseServiceRequest.java:158)
	at microsoft.exchange.webservices.data.core.ExchangeService.internalCreateItems(ExchangeService.java:598)
	at microsoft.exchange.webservices.data.core.ExchangeService.createItem(ExchangeService.java:657)
	at microsoft.exchange.webservices.data.core.service.item.Item.internalCreate(Item.java:245)
	at microsoft.exchange.webservices.data.core.service.item.EmailMessage.internalSend(EmailMessage.java:147)
	at microsoft.exchange.webservices.data.core.service.item.EmailMessage.send(EmailMessage.java:258)
	at com.project.cloud.common.email.util.DesvMailUtil.sendEmail(DesvMailUtil.java:68)
	at com.project.cloud.thirdparty.api.service.compment.MailSendService.sendMailByIoIntegral(MailSendService.java:87)
	at com.project.cloud.thirdparty.api.job.IssueIoIntegralJobHandler.notifyUser(IssueIoIntegralJobHandler.java:148)
	at com.project.cloud.thirdparty.api.job.IssueIoIntegralJobHandler.dealTask(IssueIoIntegralJobHandler.java:116)
	at com.project.cloud.thirdparty.api.job.IssueIoIntegralJobHandler.lambda$issueIoIntegralJob$0(IssueIoIntegralJobHandler.java:70)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384)
	at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:647)
	at com.project.cloud.thirdparty.api.job.IssueIoIntegralJobHandler.issueIoIntegralJob(IssueIoIntegralJobHandler.java:69)
	at com.project.cloud.thirdparty.api.job.IssueIoIntegralJobHandler$$FastClassBySpringCGLIB$$db1fcb63.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at com.project.cloud.thirdparty.api.job.IssueIoIntegralJobHandler$$EnhancerBySpringCGLIB$$8a1ea2c9.issueIoIntegralJob(<generated>)
	at sun.reflect.GeneratedMethodAccessor446.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.xxl.job.core.handler.impl.MethodJobHandler.execute(MethodJobHandler.java:29)
	at com.xxl.job.core.thread.JobThread.run(JobThread.java:152)
Caused by: microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException: The request failed. The remote server returned an error: (401)Unauthorized
	at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.validateAndEmitRequest(ServiceRequestBase.java:644)
	at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:62)
	... 23 common frames omitted
Caused by: microsoft.exchange.webservices.data.core.exception.http.HttpErrorException: The remote server returned an error: (401)Unauthorized
	at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.getEwsHttpWebResponse(ServiceRequestBase.java:723)
	at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.validateAndEmitRequest(ServiceRequestBase.java:639)
	... 24 common frames omitted

二、报错说明

从报错中,定位错误代码

com.project.cloud.thirdparty.api.job.IssueIoIntegralJobHandler.issueIoIntegralJob(IssueIoIntegralJobHandler.java:69)

2.1 定位对应的Service实现类

@Slf4j
@Service
@AllArgsConstructor
public class MailSendService {
private final MailConfigProperties mailConfigProperties;

public void notifyUser(String phone, String email, IoIntegralTask task) {
		String receiver = task.getReceiver();
		String recognizer = task.getRecognizer();
		String medal = MedalLevelEnum.getTxt(task.getMedalLevel());
		BigDecimal integral = task.getIntegral();

		String signName = smsTemplateProperties.getSignName4();
		String templateCode = smsTemplateProperties.getTemplateCode4();
		JSONObject smsTemplateParamJson = new JSONObject();
		smsTemplateParamJson.put("name", receiver);
		smsTemplateParamJson.put("name1", recognizer);
		smsTemplateParamJson.put("medal", medal);
		smsTemplateParamJson.put("num", ObjectUtil.isNotNull(integral) ? StrUtil.toString(integral) : "0");
		try {
			smsUtils.sendSms(signName, phone, templateCode, smsTemplateParamJson.toString());
		} catch (ClientException e) {
			log.error("短信发送失败: e:{}", e);
		}
		if (StrUtil.isBlank(email)) {
			return;
		}
		mailSendService.sendMailByIoIntegral(receiver, recognizer, medal, integral, email);
	}
}

2.2 定位到发邮件的组件

发现账号密码是通过使用配置文件去拿的

	public void sendMailByIoIntegral(String receiver, String recognizer, String medal, BigDecimal integral, String email) {
		MailUtil mailUtil = new MailUtil(mailConfigProperties.getUsername(), mailConfigProperties.getPassword(), mailConfigProperties.getDomain(), mailConfigProperties.getUri());
        HashMap<String, Object> param = new HashMap<String, Object>();
		param.put("to", email);
		param.put("username", "邮件用户略");
		param.put("title", "邮件标题略");
        String msgBody="邮件正文略";
		msgBody = StrUtil.format(msgBody, receiver, recognizer, medal, integral);
		param.put("item", msgBody);
		// 发送邮件
		try {
			mailUtil.sendEmail(param);
		} catch (Exception e) {
			log.error("sendMailByIoIntegral error:{}", e);
		}
	}

2.3 定位到发邮件的工具类

@Slf4j
@Data
public class MailUtil {
    private String username;
    private String password;
    private String domain;
    private String uri;
    
    public MailUtil(String username, String password, String domain, String uri) {
        this.username = username;
        this.password = password;
        this.domain = domain;
        this.uri = uri;
    }
    
    public void sendEmail(Map<String, Object> params) throws Exception {
        // 新建server版本
        ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
        // 用户名,密码,域名
        ExchangeCredentials credentials = new WebCredentials(username, password, domain);
        service.setCredentials(credentials);
        service.setUrl(new URI(uri));
        VelocityEngine ve = new VelocityEngine();
        ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        EmailMessage msg = new EmailMessage(service);
        msg.setSubject(MapUtil.getStr(params, "title"));
        log.info("email params={}", params);
        // 正文
        msg.setBody(MessageBody.getMessageBodyFromText(MapUtil.getStr(params, "item")));
        // 收件人
        msg.getToRecipients().add(MapUtil.getStr(params, "to"));
        msg.send(); // 发送
    }
}

检查Nacos中的邮箱的账号信息

emailinfo:
  username: xxxxx
  password: xxxxx
  domain: xxxxx
  uri: xxxxx

拿这个username+password进远程工具去尝试范围。
我得到了如下提示。
在这里插入图片描述

三、报错解决

不用修改代码,直接将账号密码变成长久有效即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

本本本添哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值