package com.fjhx.utils; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.lang.Assert; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.fjhx.config.exception.EmailEngineException; import com.fjhx.vo.*; import com.sun.istack.internal.NotNull; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestTemplate; import java.io.*; import java.util.HashMap; import java.util.Map; @Slf4j @Component public class EmailEngineUtil { public static String urlPrefix; public static String attachmentPath; private static final RestTemplate restTemplate = new RestTemplate(); static { restTemplate.setErrorHandler(new ResponseErrorHandler() { @Override public boolean hasError(@NotNull ClientHttpResponse response) throws IOException { HttpStatus.Series series = response.getStatusCode().series(); return !HttpStatus.Series.SUCCESSFUL.equals(series); } @Override public void handleError(@NotNull ClientHttpResponse response) throws IOException { InputStream body = response.getBody(); byte[] bytes = new byte[body.available()]; body.read(bytes); String result = new String(bytes); HttpStatus.Series series = response.getStatusCode().series(); if (HttpStatus.Series.CLIENT_ERROR.equals(series)) { throw new RuntimeException(result); } throw new EmailEngineException(result); } }); } @Value("${config.urlPrefix}") public void setUrlPrefix(String urlPrefix) { EmailEngineUtil.urlPrefix = urlPrefix; } @Value("${config.attachmentPath}") public void setAttachmentPath(String attachmentPath) { EmailEngineUtil.attachmentPath = attachmentPath; } /** * 生成邮箱 */ public static void createAccount(BindingVo bindingVo) { // 验证邮件配置参数 VerifyVo verifyVo = createVerifyVo(bindingVo); // 验证邮件配置是否正确 VerifyResult verifyResult = post("v1/verifyAccount", verifyVo, VerifyResult.class); // 解析验证结果 parsingVerifyResult(verifyResult); // 生成添加账号入参 AddAccountVo addAccountVo = createAddAccountVo(verifyVo, bindingVo.getEmail(), bindingVo.getPath()); // 添加邮箱 AddAccountResult addAccountResult = post("v1/account", addAccountVo, AddAccountResult.class); // 验证邮箱添加状态 parsingAddAccountResult(addAccountResult); } /** * 删除邮箱 */ public static void deleteAccount(String email) { delete("v1/account/" + email, new HashMap<>()); } /** * 查看文件夹的所有邮件 */ public static MessageVo getMessageList(String email, String path, int page, int size) { String url = "/v1/account/" + email + "/messages?path=" + path + "&page=" + page + "&pageSize=" + size + "&documentStore=true"; return get(url, MessageVo.class); } /** * 获取邮件明细 */ public static MessageDetailVo getMessageDetail(String email, String messageId) { String url = "v1/account/" + email + "/message/" + messageId + "?textType=html&embedAttachedImages=true&documentStore=false"; return get(url, MessageDetailVo.class); } /** * 下载附件 */ public static boolean downloadAttachment(String email, String attachmentId, String fileName) { try { File file = new File(attachmentPath + email); if (!file.exists()) { boolean mkdir = file.mkdir(); Assert.isTrue(mkdir, "创建文件夹失败"); return false; } FileOutputStream fileOutputStream = new FileOutputStream(attachmentPath + fileName); download("v1/account/" + email + "/attachment/" + attachmentId, fileOutputStream); return true; } catch (Exception e) { throw new EmailEngineException("下载附件失败"); } } public static void submit(SubmitVo submitVo) { String address = submitVo.getFrom().getAddress(); JSONObject submitJson = JSON.parseObject(JSON.toJSONString(submitVo)); post("v1/account/" + address + "/submit", submitJson, String.class); } /** * 生成验证邮箱配置实体 */ private static VerifyVo createVerifyVo(BindingVo bindingVo) { VerifyVo verifyVo = new VerifyVo(); VerifyVo.Auth auth = new VerifyVo.Auth(); auth.setUser(bindingVo.getEmail()); auth.setPass(bindingVo.getSecretKey()); VerifyVo.Tls tls = new VerifyVo.Tls(); tls.setRejectUnauthorized(true); tls.setMinVersion("TLSv1.2"); VerifyVo.Imap imap = new VerifyVo.Imap(); imap.setAuth(auth); imap.setPort(bindingVo.getImapPort()); imap.setHost(bindingVo.getImapHost()); imap.setTls(tls); imap.setSecure(true); verifyVo.setImap(imap); VerifyVo.Smtp smtp = new VerifyVo.Smtp(); smtp.setAuth(auth); smtp.setPort(bindingVo.getSmtpPort()); smtp.setHost(bindingVo.getSmtpHost()); smtp.setTls(tls); smtp.setSecure(true); verifyVo.setSmtp(smtp); return verifyVo; } /** * 解析验证结果 */ private static void parsingVerifyResult(VerifyResult verifyResult) { VerifyResult.Status imap = verifyResult.getImap(); VerifyResult.Status smtp = verifyResult.getSmtp(); Assert.notNull(imap, "imap解析结果为空"); Assert.notNull(smtp, "smtp解析结果为空"); Assert.isTrue(imap.getSuccess(), "imap解析失败:error:{} ;code:{};", imap.getError(), imap.getCode()); Assert.isTrue(smtp.getSuccess(), "smtp解析失败:error:{} ;code:{};", smtp.getError(), smtp.getCode()); } /** * 生成添加账号入参 */ private static AddAccountVo createAddAccountVo(VerifyVo verifyVo, String email, String path) { AddAccountVo addAccountVo = BeanUtil.copyProperties(verifyVo, AddAccountVo.class); addAccountVo.setAccount(email); addAccountVo.setName(email); addAccountVo.setEmail(email); addAccountVo.setPath(path); return addAccountVo; } /** * 验证添加状态 */ private static void parsingAddAccountResult(AddAccountResult addAccountResult) { String state = addAccountResult.getState(); Assert.isTrue("new".equals(state) || "existing".equals(state), "邮箱添加失败,account:{},state:{}", addAccountResult.getAccount(), addAccountResult.getState()); } private static void download(String url, OutputStream outputStream) { HttpUtil.download(urlPrefix + url, outputStream, true); } public static T get(String url, Class cls) { return RetryUtil.execute(() -> restTemplate.getForObject(urlPrefix + url, cls), 5, 5000L); } public static T post(String url, Object paramObj, Class cls) { return RetryUtil.execute(() -> restTemplate.postForObject(urlPrefix + url, paramObj, cls), 5, 3000L); } public static void delete(String url, Map map) { RetryUtil.execute(() -> { restTemplate.delete(urlPrefix + url, map); return null; }, 5, 3000L); } }