Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲精品电影久久久影院,国产亚洲综合久久,www.国产.com

          整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          springboot整合郵件服務(wù)超詳細教程

          springboot整合郵件服務(wù)超詳細教程

          者:yizhiwazi

          www.jianshu.com/p/5eb000544dd7

          基礎(chǔ)知識

          什么是SMTP?

          SMTP全稱為Simple Mail Transfer Protocol(簡單郵件傳輸協(xié)議),它是一組用于從源地址到目的地址傳輸郵件的規(guī)范,通過它來控制郵件的中轉(zhuǎn)方式。SMTP認證要求必須提供賬號和密碼才能登陸服務(wù)器,其設(shè)計目的在于避免用戶受到垃圾郵件的侵擾。

          什么是IMAP?

          IMAP全稱為Internet Message Access Protocol(互聯(lián)網(wǎng)郵件訪問協(xié)議),IMAP允許從郵件服務(wù)器上獲取郵件的信息、下載郵件等。IMAP與POP類似,都是一種郵件獲取協(xié)議。

          什么是POP3?

          POP3全稱為Post Office Protocol 3(郵局協(xié)議),POP3支持客戶端遠程管理服務(wù)器端的郵件。POP3常用于“離線”郵件處理,即允許客戶端下載服務(wù)器郵件,然后服務(wù)器上的郵件將會被刪除。目前很多POP3的郵件服務(wù)器只提供下載郵件功能,服務(wù)器本身并不刪除郵件,這種屬于改進版的POP3協(xié)議。

          IMAP和POP3協(xié)議有什么不同呢?

          兩者最大的區(qū)別在于,IMAP允許雙向通信,即在客戶端的操作會反饋到服務(wù)器上,例如在客戶端收取郵件、標記已讀等操作,服務(wù)器會跟著同步這些操作。而對于POP協(xié)議雖然也允許客戶端下載服務(wù)器郵件,但是在客戶端的操作并不會同步到服務(wù)器上面的,例如在客戶端收取或標記已讀郵件,服務(wù)器不會同步這些操作。

          進階知識

          什么是JavaMailSender和JavaMailSenderImpl?

          JavaMailSender和JavaMailSenderImpl 是Spring官方提供的集成郵件服務(wù)的接口和實現(xiàn)類,以簡單高效的設(shè)計著稱,目前是Java后端發(fā)送郵件和集成郵件服務(wù)的主流工具。

          如何通過JavaMailSenderImpl發(fā)送郵件?

          非常簡單,直接在業(yè)務(wù)類注入JavaMailSenderImpl并調(diào)用send方法發(fā)送郵件。其中簡單郵件可以通過SimpleMailMessage來發(fā)送郵件,而復(fù)雜的郵件(例如添加附件)可以借助MimeMessageHelper來構(gòu)建MimeMessage發(fā)送郵件。例如:

              @Autowired
              private JavaMailSenderImpl mailSender;
          
              public void sendMail() throws MessagingException {
                  //簡單郵件
                  SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
                  simpleMailMessage.setFrom("admin@163.com");
                  simpleMailMessage.setTo("socks@qq.com");
                  simpleMailMessage.setSubject("Happy New Year");
                  simpleMailMessage.setText("新年快樂!");
                  mailSender.send(simpleMailMessage);
          
                  //復(fù)雜郵件
                  MimeMessage mimeMessage = mailSender.createMimeMessage();
                  MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
                  messageHelper.setFrom("admin@163.com");
                  messageHelper.setTo("socks@qq.com");
                  messageHelper.setSubject("Happy New Year");
                  messageHelper.setText("新年快樂!");
                  messageHelper.addInline("doge.gif", new File("xx/xx/doge.gif"));
                  messageHelper.addAttachment("work.docx", new File("xx/xx/work.docx"));
                  mailSender.send(mimeMessage);
              }

          為什么JavaMailSenderImpl 能夠開箱即用 ?

          所謂開箱即用其實就是基于官方內(nèi)置的自動配置,翻看源碼可知曉郵件自動配置類(MailSenderPropertiesConfiguration) 為上下文提供了郵件服務(wù)實例(JavaMailSenderImpl)。具體源碼如下:

          @Configuration
          @ConditionalOnProperty(prefix = "spring.mail", name = "host")
          class MailSenderPropertiesConfiguration {
              private final MailProperties properties;
              MailSenderPropertiesConfiguration(MailProperties properties) {
                  this.properties = properties;
              }
              @Bean
              @ConditionalOnMissingBean
              public JavaMailSenderImpl mailSender() {
                  JavaMailSenderImpl sender = new JavaMailSenderImpl();
                  applyProperties(sender);
                  return sender;
              }

          其中MailProperties是關(guān)于郵件服務(wù)器的配置信息,具體源碼如下:

          @ConfigurationProperties(prefix = "spring.mail")
          public class MailProperties {
              private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
              private String host;
              private Integer port;
              private String username;
              private String password;
              private String protocol = "smtp";
              private Charset defaultEncoding = DEFAULT_CHARSET;
              private Map<String, String> properties = new HashMap<>();
          }

          使用教程

          一、開啟郵件服務(wù)

          登陸網(wǎng)易郵箱163,在設(shè)置中打開并勾選POP3/SMTP/IMAP服務(wù),然后會得到一個授權(quán)碼,這個郵箱和授權(quán)碼將用作登陸認證。

          二、配置郵件服務(wù)

          首先咱們通過 Spring Initializr 創(chuàng)建工程springboot-send-mail,如圖所示:

          然后在pom.xml 引入web、thymeleaf 和spring-boot-starter-mail等相關(guān)依賴。例如:

              <dependencies>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-web</artifactId>
                  </dependency>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-thymeleaf</artifactId>
                  </dependency>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-mail</artifactId>
                  </dependency>
                  <dependency>
                      <groupId>org.webjars</groupId>
                      <artifactId>webjars-locator-core</artifactId>
                  </dependency>
                  <dependency>
                      <groupId>org.webjars</groupId>
                      <artifactId>jquery</artifactId>
                      <version>3.3.1</version>
                  </dependency>
                  <dependency>
                      <groupId>org.webjars</groupId>
                      <artifactId>bootstrap</artifactId>
                      <version>3.3.7</version>
                  </dependency>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-devtools</artifactId>
                      <scope>runtime</scope>
                  </dependency>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-test</artifactId>
                      <scope>test</scope>
                  </dependency>
              </dependencies>

          根據(jù)前面提到的配置項(MailProperties)填寫相關(guān)配置信息,其中spring.mail.username 表示連接郵件服務(wù)器時認證的登陸賬號,可以是普通的手機號或者登陸賬號,并非一定是郵箱,為了解決這個問題,推薦大家在spring.mail. properties.from填寫郵件發(fā)信人即真實郵箱。

          然后在application.yml添加如下配置:

          spring:
            mail:
              host: smtp.163.com #SMTP服務(wù)器地址
              username:  socks #登陸賬號
              password: 123456 #登陸密碼(或授權(quán)碼)
              properties:
                from: socks@163.com #郵件發(fā)信人(即真實郵箱)
            thymeleaf:
              cache: false
              prefix: classpath:/views/
            servlet:
              multipart:
                max-file-size: 10MB #限制單個文件大小
                max-request-size: 50MB #限制請求總量

          透過前面的進階知識,我們知道在發(fā)送郵件前,需要先構(gòu)建 SimpleMailMessage或 MimeMessage 郵件信息類來填寫郵件標題、郵件內(nèi)容等信息,最后提交給JavaMailSenderImpl發(fā)送郵件,這樣看起來沒什么問題,也能實現(xiàn)既定目標,但在實際使用中會出現(xiàn)大量零散和重復(fù)的代碼,還不便于保存郵件到數(shù)據(jù)庫。

          那么優(yōu)雅的發(fā)送郵件應(yīng)該是如何的呢?應(yīng)該屏蔽掉這些構(gòu)建信息和發(fā)送郵件的細節(jié),不管是簡單還是復(fù)雜郵件,都可以通過統(tǒng)一的API來發(fā)送郵件。例如:mailService.send(mailVo) 。

          例如通過郵件信息類(MailVo) 來保存發(fā)送郵件時的郵件主題、郵件內(nèi)容等信息 :

          package com.hehe.vo;
          
          public class MailVo {
              private String id;//郵件id
              private String from;//郵件發(fā)送人
              private String to;//郵件接收人(多個郵箱則用逗號","隔開)
              private String subject;//郵件主題
              private String text;//郵件內(nèi)容
              private Date sentDate;//發(fā)送時間
              private String cc;//抄送(多個郵箱則用逗號","隔開)
              private String bcc;//密送(多個郵箱則用逗號","隔開)
              private String status;//狀態(tài)
              private String error;//報錯信息
              @JsonIgnore
              private MultipartFile[] multipartFiles;//郵件附件
             //省略GET&SET方法
          }

          三、發(fā)送郵件和附件

          ===========接下來正式介紹發(fā)送郵件的最核心邏輯 前方高能=============

          除了發(fā)送郵件之外,還包括檢測郵件和保存郵件等操作,例如:

          • 檢測郵件 checkMail(); 首先校驗郵件收信人、郵件主題和郵件內(nèi)容這些必填項,若為空則拒絕發(fā)送。
          • 發(fā)送郵件 sendMimeMail(); 其次通過MimeMessageHelper來解析MailVo并構(gòu)建MimeMessage傳輸郵件。
          • 保存郵件 sendMimeMail(); 最后將郵件保存到數(shù)據(jù)庫,便于統(tǒng)計和追查郵件問題。

          本案例郵件業(yè)務(wù)類 MailService 的具體源碼如下:

          package com.hehe.service;
          
          /**
           * 郵件業(yè)務(wù)類 MailService
           */
          @Service
          public class MailService {
          
              private Logger logger = LoggerFactory.getLogger(getClass());//提供日志類
          
              @Autowired
              private JavaMailSenderImpl mailSender;//注入郵件工具類
          
          
              /**
               * 發(fā)送郵件
               */
              public MailVo sendMail(MailVo mailVo) {
                  try {
                      checkMail(mailVo); //1.檢測郵件
                      sendMimeMail(mailVo); //2.發(fā)送郵件
                      return saveMail(mailVo); //3.保存郵件
                  } catch (Exception e) {
                      logger.error("發(fā)送郵件失敗:", e);//打印錯誤信息
                      mailVo.setStatus("fail");
                      mailVo.setError(e.getMessage());
                      return mailVo;
                  }
          
              }
          
              //檢測郵件信息類
              private void checkMail(MailVo mailVo) {
                  if (StringUtils.isEmpty(mailVo.getTo())) {
                      throw new RuntimeException("郵件收信人不能為空");
                  }
                  if (StringUtils.isEmpty(mailVo.getSubject())) {
                      throw new RuntimeException("郵件主題不能為空");
                  }
                  if (StringUtils.isEmpty(mailVo.getText())) {
                      throw new RuntimeException("郵件內(nèi)容不能為空");
                  }
              }
          
              //構(gòu)建復(fù)雜郵件信息類
              private void sendMimeMail(MailVo mailVo) {
                  try {
                      MimeMessageHelper messageHelper = new MimeMessageHelper(mailSender.createMimeMessage(), true);//true表示支持復(fù)雜類型
                      mailVo.setFrom(getMailSendFrom());//郵件發(fā)信人從配置項讀取
                      messageHelper.setFrom(mailVo.getFrom());//郵件發(fā)信人
                      messageHelper.setTo(mailVo.getTo().split(","));//郵件收信人
                      messageHelper.setSubject(mailVo.getSubject());//郵件主題
                      messageHelper.setText(mailVo.getText());//郵件內(nèi)容
                      if (!StringUtils.isEmpty(mailVo.getCc())) {//抄送
                          messageHelper.setCc(mailVo.getCc().split(","));
                      }
                      if (!StringUtils.isEmpty(mailVo.getBcc())) {//密送
                          messageHelper.setCc(mailVo.getBcc().split(","));
                      }
                      if (mailVo.getMultipartFiles() != null) {//添加郵件附件
                          for (MultipartFile multipartFile : mailVo.getMultipartFiles()) {
                              messageHelper.addAttachment(multipartFile.getOriginalFilename(), multipartFile);
                          }
                      }
                      if (StringUtils.isEmpty(mailVo.getSentDate())) {//發(fā)送時間
                          mailVo.setSentDate(new Date());
                          messageHelper.setSentDate(mailVo.getSentDate());
                      }
                      mailSender.send(messageHelper.getMimeMessage());//正式發(fā)送郵件
                      mailVo.setStatus("ok");
                      logger.info("發(fā)送郵件成功:{}->{}", mailVo.getFrom(), mailVo.getTo());
                  } catch (Exception e) {
                      throw new RuntimeException(e);//發(fā)送失敗
                  }
              }
          
              //保存郵件
              private MailVo saveMail(MailVo mailVo) {
                  //將郵件保存到數(shù)據(jù)庫..
                  return mailVo;
              }
          
              //獲取郵件發(fā)信人
              public String getMailSendFrom() {
                  return mailSender.getJavaMailProperties().getProperty("from");
              }
          }

          搞定了發(fā)送郵件最核心的業(yè)務(wù)邏輯,接下來咱們寫一個簡單頁面用來發(fā)送郵件。

          首先寫好跟頁面交互的控制器 MailController,具體源碼如下:

          @RestController
          public class MailController {
              @Autowired
              private MailService mailService;
          
              /**
               * 發(fā)送郵件的主界面
               */
              @GetMapping("/")
              public ModelAndView index() {
                  ModelAndView mv = new ModelAndView("mail/sendMail");//打開發(fā)送郵件的頁面
                  mv.addObject("from", mailService.getMailSendFrom());//郵件發(fā)信人
                  return mv;
              }
              /**
               * 發(fā)送郵件
               */
              @PostMapping("/mail/send")
              public MailVo sendMail(MailVo mailVo, MultipartFile[] files) {
                  mailVo.setMultipartFiles(files);
                  return mailService.sendMail(mailVo);//發(fā)送郵件和附件
              }
          }

          然后在/resources/views/mail目錄新建sendMail.html,具體源碼如下:

          <!DOCTYPE html>
          <html xmlns:th="http://www.thymeleaf.org">
          
          <head>
              <meta charset="UTF-8"/>
              <title>發(fā)送郵件</title>
              <link th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" rel="stylesheet" type="text/css"/>
              <script th:src="@{/webjars/jquery/jquery.min.js}"></script>
              <script th:href="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
          
          </head>
          
          <body>
          <div class="col-md-6" style="margin:20px;padding:20px;border: #E0E0E0 1px solid;">
              <marquee behavior="alternate" onfinish="alert(12)" id="mq"
                       onMouseOut="this.start();$('#egg').text('嗯 真聽話!');"
                       onMouseOver="this.stop();$('#egg').text('有本事放開我呀!');">
                  <h5 id="egg">祝大家新年快樂!</h5><img id="doge" src="http://pics.sc.chinaz.com/Files/pic/faces/3709/7.gif" alt="">
              </marquee>
          
              <form class="form-horizontal" id="mailForm">
                  <div class="form-group">
                      <label class="col-md-2 control-label">郵件發(fā)信人:</label>
                      <div class="col-md-6">
                          <input class="form-control" id="from" name="from" th:value="${from}" readonly="readonly">
                      </div>
                  </div>
                  <div class="form-group">
                      <label class="col-md-2 control-label">郵件收信人:</label>
                      <div class="col-md-6">
                          <input class="form-control" id="to" name="to" title="多個郵箱使用,隔開">
                      </div>
                  </div>
                  <div class="form-group">
                      <label class="col-md-2 control-label">郵件主題:</label>
                      <div class="col-md-6">
                          <input class="form-control" id="subject" name="subject">
                      </div>
                  </div>
                  <div class="form-group">
                      <label class="col-md-2 control-label">郵件內(nèi)容:</label>
                      <div class="col-md-6">
                          <textarea class="form-control" id="text" name="text" rows="5"></textarea>
                      </div>
                  </div>
                  <div class="form-group">
                      <label class="col-md-2 control-label">郵件附件:</label>
                      <div class="col-md-6">
                          <input class="form-control" id="files" name="files" type="file" multiple="multiple">
                      </div>
                  </div>
                  <div class="form-group">
                      <label class="col-md-2 control-label">郵件操作:</label>
                      <div class="col-md-3">
                          <a class="form-control btn btn-primary" onclick="sendMail()">發(fā)送郵件</a>
                      </div>
                      <div class="col-md-3">
                          <a class="form-control btn btn-default" onclick="clearForm()">清空</a>
                      </div>
                  </div>
              </form>
          
              <script th:inline="javascript">
                  var appCtx = [[${#request.getContextPath()}]];
          
                  function sendMail() {
          
                      var formData = new FormData($('#mailForm')[0]);
                      $.ajax({
                          url: appCtx + '/mail/send',
                          type: "POST",
                          data: formData,
                          contentType: false,
                          processData: false,
                          success: function (result) {
                              alert(result.status === 'ok' ? "發(fā)送成功!" : "你被Doge嘲諷了:" + result.error);
                          },
                          error: function () {
                              alert("發(fā)送失敗!");
                          }
                      });
                  }
          
                  function clearForm() {
                      $('#mailForm')[0].reset();
                  }
          
                  setInterval(function () {
                      var total = $('#mq').width();
                      var width = $('#doge').width();
                      var left = $('#doge').offset().left;
                      if (left <= width / 2 + 20) {
                          $('#doge').css('transform', 'rotateY(180deg)')
                      }
                      if (left >= total - width / 2 - 40) {
                          $('#doge').css('transform', 'rotateY(-360deg)')
                      }
                  });
              </script>
          </div>
          </body>
          </html>

          四、測試發(fā)送郵件

          如果是初學(xué)者,建議大家先下載源碼,修改配置后運行工程,成功后再自己重新寫一遍代碼,這樣有助于加深記憶。

          啟動工程并訪問:http://localhost:8080 然后可以看到發(fā)送郵件的主界面如下:

          然后填寫你的小號郵箱,點擊發(fā)送郵件,若成功則可以登陸小號郵箱查看郵件和剛才上傳的附件。

          至此發(fā)送郵件代碼全部完成,歡迎大家下載并關(guān)注Github 源碼。

          五、常見失敗編碼

          如果企業(yè)定制了郵件服務(wù)器,自然會記錄郵件日志,根據(jù)錯誤編碼存儲日志有利于日常維護。

          例如這些由網(wǎng)易郵箱提供的錯誤編碼標識:

          421

          • 421 HL:REP 該IP發(fā)送行為異常,存在接收者大量不存在情況,被臨時禁止連接。請檢查是否有用戶發(fā)送病毒或者垃圾郵件,并核對發(fā)送列表有效性;
          • 421 HL:ICC 該IP同時并發(fā)連接數(shù)過大,超過了網(wǎng)易的限制,被臨時禁止連接。請檢查是否有用戶發(fā)送病毒或者垃圾郵件,并降低IP并發(fā)連接數(shù)量;
          • 421 HL:IFC 該IP短期內(nèi)發(fā)送了大量信件,超過了網(wǎng)易的限制,被臨時禁止連接。請檢查是否有用戶發(fā)送病毒或者垃圾郵件,并降低發(fā)送頻率;
          • 421 HL:MEP 該IP發(fā)送行為異常,存在大量偽造發(fā)送域域名行為,被臨時禁止連接。請檢查是否有用戶發(fā)送病毒或者垃圾郵件,并使用真實有效的域名發(fā)送;

          450

          • 450 MI:CEL 發(fā)送方出現(xiàn)過多的錯誤指令。請檢查發(fā)信程序;
          • 450 MI:DMC 當(dāng)前連接發(fā)送的郵件數(shù)量超出限制。請減少每次連接中投遞的郵件數(shù)量;
          • 450 MI:CCL 發(fā)送方發(fā)送超出正常的指令數(shù)量。請檢查發(fā)信程序;
          • 450 RP:DRC 當(dāng)前連接發(fā)送的收件人數(shù)量超出限制。請控制每次連接投遞的郵件數(shù)量;
          • 450 RP:CCL 發(fā)送方發(fā)送超出正常的指令數(shù)量。請檢查發(fā)信程序;
          • 450 DT:RBL 發(fā)信IP位于一個或多個RBL里。請參考http://www.rbls.org/關(guān)于RBL的相關(guān)信息;
          • 450 WM:BLI 該IP不在網(wǎng)易允許的發(fā)送地址列表里;
          • 450 WM:BLU 此用戶不在網(wǎng)易允許的發(fā)信用戶列表里;

          451

          • 451 DT:SPM ,please try again 郵件正文帶有垃圾郵件特征或發(fā)送環(huán)境缺乏規(guī)范性,被臨時拒收。請保持郵件隊列,兩分鐘后重投郵件。需調(diào)整郵件內(nèi)容或優(yōu)化發(fā)送環(huán)境;
          • 451 Requested mail action not taken: too much fail authentication 登錄失敗次數(shù)過多,被臨時禁止登錄。請檢查密碼與帳號驗證設(shè)置;
          • 451 RP:CEL 發(fā)送方出現(xiàn)過多的錯誤指令。請檢查發(fā)信程序;
          • 451 MI:DMC 當(dāng)前連接發(fā)送的郵件數(shù)量超出限制。請控制每次連接中投遞的郵件數(shù)量;
          • 451 MI:SFQ 發(fā)信人在15分鐘內(nèi)的發(fā)信數(shù)量超過限制,請控制發(fā)信頻率;
          • 451 RP:QRC 發(fā)信方短期內(nèi)累計的收件人數(shù)量超過限制,該發(fā)件人被臨時禁止發(fā)信。請降低該用戶發(fā)信頻率;
          • 451 Requested action aborted: local error in processing 系統(tǒng)暫時出現(xiàn)故障,請稍后再次嘗試發(fā)送;

          500

          • 500 Error: bad syntaxU 發(fā)送的smtp命令語法有誤;
          • 550 MI:NHD HELO命令不允許為空;
          • 550 MI:IMF 發(fā)信人電子郵件地址不合規(guī)范。請參考http://www.rfc-editor.org/關(guān)于電子郵件規(guī)范的定義;
          • 550 MI:SPF 發(fā)信IP未被發(fā)送域的SPF許可。請參考http://www.openspf.org/關(guān)于SPF規(guī)范的定義;
          • 550 MI:DMA 該郵件未被發(fā)信域的DMARC許可。請參考http://dmarc.org/關(guān)于DMARC規(guī)范的定義;
          • 550 MI:STC 發(fā)件人當(dāng)天的連接數(shù)量超出了限定數(shù)量,當(dāng)天不再接受該發(fā)件人的郵件。請控制連接次數(shù);
          • 550 RP:FRL 網(wǎng)易郵箱不開放匿名轉(zhuǎn)發(fā)(Open relay);
          • 550 RP:RCL 群發(fā)收件人數(shù)量超過了限額,請減少每封郵件的收件人數(shù)量;
          • 550 RP:TRC 發(fā)件人當(dāng)天內(nèi)累計的收件人數(shù)量超過限制,當(dāng)天不再接受該發(fā)件人的郵件。請降低該用戶發(fā)信頻率;
          • 550 DT:SPM 郵件正文帶有很多垃圾郵件特征或發(fā)送環(huán)境缺乏規(guī)范性。需調(diào)整郵件內(nèi)容或優(yōu)化發(fā)送環(huán)境;
          • 550 Invalid User 請求的用戶不存在;
          • 550 User in blacklist 該用戶不被允許給網(wǎng)易用戶發(fā)信;
          • 550 User suspended 請求的用戶處于禁用或者凍結(jié)狀態(tài);
          • 550 Requested mail action not taken: too much recipient 群發(fā)數(shù)量超過了限額;

          552

          • 552 Illegal Attachment 不允許發(fā)送該類型的附件,包括以.uu .pif .scr .mim .hqx .bhx .cmd .vbs .bat .com .vbe .vb .js .wsh等結(jié)尾的附件;
          • 552 Requested mail action aborted: exceeded mailsize limit 發(fā)送的信件大小超過了網(wǎng)易郵箱允許接收的最大限制;

          553

          • 553 Requested action not taken: NULL sender is not allowed 不允許發(fā)件人為空,請使用真實發(fā)件人發(fā)送;
          • 553 Requested action not taken: Local user only SMTP類型的機器只允許發(fā)信人是本站用戶;
          • 553 Requested action not taken: no smtp MX only MX類型的機器不允許發(fā)信人是本站用戶;
          • 553 authentication is required SMTP需要身份驗證,請檢查客戶端設(shè)置;

          554

          • 554 DT:SPM 發(fā)送的郵件內(nèi)容包含了未被許可的信息,或被系統(tǒng)識別為垃圾郵件。請檢查是否有用戶發(fā)送病毒或者垃圾郵件;
          • 554 DT:SUM 信封發(fā)件人和信頭發(fā)件人不匹配;
          • 554 IP is rejected, smtp auth error limit exceed 該IP驗證失敗次數(shù)過多,被臨時禁止連接。請檢查驗證信息設(shè)置;
          • 554 HL:IHU 發(fā)信IP因發(fā)送垃圾郵件或存在異常的連接行為,被暫時掛起。請檢測發(fā)信IP在歷史上的發(fā)信情況和發(fā)信程序是否存在異常;
          • 554 HL:IPB 該IP不在網(wǎng)易允許的發(fā)送地址列表里;
          • 554 MI:STC 發(fā)件人當(dāng)天內(nèi)累計郵件數(shù)量超過限制,當(dāng)天不再接受該發(fā)件人的投信。請降低發(fā)信頻率;
          • 554 MI:SPB 此用戶不在網(wǎng)易允許的發(fā)信用戶列表里;
          • 554 IP in blacklist 該IP不在網(wǎng)易允許的發(fā)送地址列表里。

          質(zhì)文章,及時送達

          鏈接 | www.jianshu.com/p/5eb000544dd7

          基礎(chǔ)知識

          什么是SMTP?

          SMTP全稱為Simple Mail Transfer Protocol(簡單郵件傳輸協(xié)議),它是一組用于從源地址到目的地址傳輸郵件的規(guī)范,通過它來控制郵件的中轉(zhuǎn)方式。SMTP認證要求必須提供賬號和密碼才能登陸服務(wù)器,其設(shè)計目的在于避免用戶受到垃圾郵件的侵擾。

          什么是IMAP?

          IMAP全稱為Internet Message Access Protocol(互聯(lián)網(wǎng)郵件訪問協(xié)議),IMAP允許從郵件服務(wù)器上獲取郵件的信息、下載郵件等。IMAP與POP類似,都是一種郵件獲取協(xié)議。

          什么是POP3?

          POP3全稱為Post Office Protocol 3(郵局協(xié)議),POP3支持客戶端遠程管理服務(wù)器端的郵件。POP3常用于“離線”郵件處理,即允許客戶端下載服務(wù)器郵件,然后服務(wù)器上的郵件將會被刪除。目前很多POP3的郵件服務(wù)器只提供下載郵件功能,服務(wù)器本身并不刪除郵件,這種屬于改進版的POP3協(xié)議。

          IMAP和POP3協(xié)議有什么不同呢?

          兩者最大的區(qū)別在于,IMAP允許雙向通信,即在客戶端的操作會反饋到服務(wù)器上,例如在客戶端收取郵件、標記已讀等操作,服務(wù)器會跟著同步這些操作。而對于POP協(xié)議雖然也允許客戶端下載服務(wù)器郵件,但是在客戶端的操作并不會同步到服務(wù)器上面的,例如在客戶端收取或標記已讀郵件,服務(wù)器不會同步這些操作。

          進階知識

          什么是JavaMailSender和JavaMailSenderImpl?

          JavaMailSender和JavaMailSenderImpl 是Spring官方提供的集成郵件服務(wù)的接口和實現(xiàn)類,以簡單高效的設(shè)計著稱,目前是Java后端發(fā)送郵件和集成郵件服務(wù)的主流工具。

          如何通過JavaMailSenderImpl發(fā)送郵件?

          非常簡單,直接在業(yè)務(wù)類注入JavaMailSenderImpl并調(diào)用send方法發(fā)送郵件。其中簡單郵件可以通過SimpleMailMessage來發(fā)送郵件,而復(fù)雜的郵件(例如添加附件)可以借助MimeMessageHelper來構(gòu)建MimeMessage發(fā)送郵件。例如:

          @Autowired
          private JavaMailSenderImpl mailSender;

          public void sendMail throws MessagingException {
          //簡單郵件
          SimpleMailMessage simpleMailMessage=new SimpleMailMessage;
          simpleMailMessage.setFrom("admin@163.com");
          simpleMailMessage.setTo("socks@qq.com");
          simpleMailMessage.setSubject("Happy New Year");
          simpleMailMessage.setText("新年快樂!");
          mailSender.send(simpleMailMessage);

          //復(fù)雜郵件
          MimeMessage mimeMessage=mailSender.createMimeMessage;
          MimeMessageHelper messageHelper=new MimeMessageHelper(mimeMessage);
          messageHelper.setFrom("admin@163.com");
          messageHelper.setTo("socks@qq.com");
          messageHelper.setSubject("Happy New Year");
          messageHelper.setText("新年快樂!");
          messageHelper.addInline("doge.gif", new File("xx/xx/doge.gif"));
          messageHelper.addAttachment("work.docx", new File("xx/xx/work.docx"));
          mailSender.send(mimeMessage);
          }

          為什么JavaMailSenderImpl 能夠開箱即用 ?

          所謂開箱即用其實就是基于官方內(nèi)置的自動配置,翻看源碼可知曉郵件自動配置類(MailSenderPropertiesConfiguration) 為上下文提供了郵件服務(wù)實例(JavaMailSenderImpl)。具體源碼如下:

          @Configuration
          @ConditionalOnProperty(prefix="spring.mail", name="host")
          classMailSenderPropertiesConfiguration{
          private final MailProperties properties;
          MailSenderPropertiesConfiguration(MailProperties properties) {
          this.properties=properties;
          }
          @Bean
          @ConditionalOnMissingBean
          public JavaMailSenderImpl mailSender {
          JavaMailSenderImpl sender=new JavaMailSenderImpl;
          applyProperties(sender);
          return sender;
          }

          其中MailProperties是關(guān)于郵件服務(wù)器的配置信息,具體源碼如下:

          @ConfigurationProperties(prefix="spring.mail")
          public class MailProperties {
          private static final Charset DEFAULT_CHARSET=StandardCharsets.UTF_8;
          private String host;
          private Integer port;
          private String username;
          private String password;
          private String protocol="smtp";
          private Charset defaultEncoding=DEFAULT_CHARSET;
          private Map<String, String> properties=new HashMap<>;
          }

          使用教程

          一、開啟郵件服務(wù)

          登陸網(wǎng)易郵箱163,在設(shè)置中打開并勾選POP3/SMTP/IMAP服務(wù),然后會得到一個授權(quán)碼,這個郵箱和授權(quán)碼將用作登陸認證。

          二、配置郵件服務(wù)

          首先咱們通過 Spring Initializr 創(chuàng)建工程springboot-send-mail,如圖所示:

          然后在pom.xml 引入web、thymeleaf 和spring-boot-starter-mail等相關(guān)依賴。例如:

          <dependencies>
          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-thymeleaf</artifactId>
          </dependency>
          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-mail</artifactId>
          </dependency>
          <dependency>
          <groupId>org.webjars</groupId>
          <artifactId>webjars-locator-core</artifactId>
          </dependency>
          <dependency>
          <groupId>org.webjars</groupId>
          <artifactId>jquery</artifactId>
          <version>3.3.1</version>
          </dependency>
          <dependency>
          <groupId>org.webjars</groupId>
          <artifactId>bootstrap</artifactId>
          <version>3.3.7</version>
          </dependency>
          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
          <scope>runtime</scope>
          </dependency>
          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
          </dependency>
          </dependencies>

          根據(jù)前面提到的配置項(MailProperties)填寫相關(guān)配置信息,其中spring.mail.username 表示連接郵件服務(wù)器時認證的登陸賬號,可以是普通的手機號或者登陸賬號,并非一定是郵箱,為了解決這個問題,推薦大家在spring.mail. properties.from填寫郵件發(fā)信人即真實郵箱。

          Tips:關(guān)注微信公眾號:Java后端,每日提送技術(shù)博文。

          然后在application.yml添加如下配置:

          spring:
          mail:
          host: smtp.163.com #SMTP服務(wù)器地址
          username: socks #登陸賬號
          password: 123456 #登陸密碼(或授權(quán)碼)
          properties:
          from: socks@163.com #郵件發(fā)信人(即真實郵箱)
          thymeleaf:
          cache: false
          prefix: classpath:/views/
          servlet:
          multipart:
          max-file-size: 10MB #限制單個文件大小
          max-request-size: 50MB #限制請求總量

          透過前面的進階知識,我們知道在發(fā)送郵件前,需要先構(gòu)建 SimpleMailMessage或 MimeMessage 郵件信息類來填寫郵件標題、郵件內(nèi)容等信息,最后提交給JavaMailSenderImpl發(fā)送郵件,這樣看起來沒什么問題,也能實現(xiàn)既定目標,但在實際使用中會出現(xiàn)大量零散和重復(fù)的代碼,還不便于保存郵件到數(shù)據(jù)庫。

          那么優(yōu)雅的發(fā)送郵件應(yīng)該是如何的呢?應(yīng)該屏蔽掉這些構(gòu)建信息和發(fā)送郵件的細節(jié),不管是簡單還是復(fù)雜郵件,都可以通過統(tǒng)一的API來發(fā)送郵件。例如:mailService.send(mailVo) 。

          例如通過郵件信息類(MailVo) 來保存發(fā)送郵件時的郵件主題、郵件內(nèi)容等信息 :

          package com.hehe.vo;

          public class MailVo {
          private String id;//郵件id
          private String from;//郵件發(fā)送人
          private String to;//郵件接收人(多個郵箱則用逗號","隔開)
          private String subject;//郵件主題
          private String text;//郵件內(nèi)容
          private Date sentDate;//發(fā)送時間
          private String cc;//抄送(多個郵箱則用逗號","隔開)
          private String bcc;//密送(多個郵箱則用逗號","隔開)
          private String status;//狀態(tài)
          private String error;//報錯信息
          @JsonIgnore
          private MultipartFile multipartFiles;//郵件附件
          //省略GET&SET方法
          }

          三、發(fā)送郵件和附件

          除了發(fā)送郵件之外,還包括檢測郵件和保存郵件等操作,例如:

          • 檢測郵件 checkMail; 首先校驗郵件收信人、郵件主題和郵件內(nèi)容這些必填項,若為空則拒絕發(fā)送。

          • 發(fā)送郵件 sendMimeMail; 其次通過MimeMessageHelper來解析MailVo并構(gòu)建MimeMessage傳輸郵件。

          • 保存郵件 sendMimeMail; 最后將郵件保存到數(shù)據(jù)庫,便于統(tǒng)計和追查郵件問題。

          本案例郵件業(yè)務(wù)類 MailService 的具體源碼如下:

          package com.hehe.service;

          /**
          * 郵件業(yè)務(wù)類 MailService
          */
          @Service
          publicclassMailService{

          private Logger logger=LoggerFactory.getLogger(getClass);//提供日志類

          @Autowired
          private JavaMailSenderImpl mailSender;//注入郵件工具類


          /**
          * 發(fā)送郵件
          */
          public MailVo sendMail(MailVo mailVo) {
          try {
          checkMail(mailVo); //1.檢測郵件
          sendMimeMail(mailVo); //2.發(fā)送郵件
          return saveMail(mailVo); //3.保存郵件
          } catch (Exception e) {
          logger.error("發(fā)送郵件失敗:", e);//打印錯誤信息
          mailVo.setStatus("fail");
          mailVo.setError(e.getMessage);
          return mailVo;
          }

          }

          //檢測郵件信息類
          privatevoidcheckMail(MailVo mailVo) {
          if (StringUtils.isEmpty(mailVo.getTo)) {
          throw new RuntimeException("郵件收信人不能為空");
          }
          if (StringUtils.isEmpty(mailVo.getSubject)) {
          throw new RuntimeException("郵件主題不能為空");
          }
          if (StringUtils.isEmpty(mailVo.getText)) {
          throw new RuntimeException("郵件內(nèi)容不能為空");
          }
          }

          //構(gòu)建復(fù)雜郵件信息類
          privatevoidsendMimeMail(MailVo mailVo) {
          try {
          MimeMessageHelper messageHelper=new MimeMessageHelper(mailSender.createMimeMessage, true);//true表示支持復(fù)雜類型
          mailVo.setFrom(getMailSendFrom);//郵件發(fā)信人從配置項讀取
          messageHelper.setFrom(mailVo.getFrom);//郵件發(fā)信人
          messageHelper.setTo(mailVo.getTo.split(","));//郵件收信人
          messageHelper.setSubject(mailVo.getSubject);//郵件主題
          messageHelper.setText(mailVo.getText);//郵件內(nèi)容
          if (!StringUtils.isEmpty(mailVo.getCc)) {//抄送
          messageHelper.setCc(mailVo.getCc.split(","));
          }
          if (!StringUtils.isEmpty(mailVo.getBcc)) {//密送
          messageHelper.setCc(mailVo.getBcc.split(","));
          }
          if (mailVo.getMultipartFiles !=) {//添加郵件附件
          for (MultipartFile multipartFile : mailVo.getMultipartFiles) {
          messageHelper.addAttachment(multipartFile.getOriginalFilename, multipartFile);
          }
          }
          if (StringUtils.isEmpty(mailVo.getSentDate)) {//發(fā)送時間
          mailVo.setSentDate(new Date);
          messageHelper.setSentDate(mailVo.getSentDate);
          }
          mailSender.send(messageHelper.getMimeMessage);//正式發(fā)送郵件
          mailVo.setStatus("ok");
          logger.info("發(fā)送郵件成功:{}->{}", mailVo.getFrom, mailVo.getTo);
          } catch (Exception e) {
          throw new RuntimeException(e);//發(fā)送失敗
          }
          }

          //保存郵件
          private MailVo saveMail(MailVo mailVo) {
          //將郵件保存到數(shù)據(jù)庫..
          return mailVo;
          }

          //獲取郵件發(fā)信人
          public String getMailSendFrom {
          return mailSender.getJavaMailProperties.getProperty("from");
          }
          }

          搞定了發(fā)送郵件最核心的業(yè)務(wù)邏輯,接下來咱們寫一個簡單頁面用來發(fā)送郵件。

          首先寫好跟頁面交互的控制器 MailController,具體源碼如下:

          @RestController
          publicclassMailController{
          @Autowired
          private MailService mailService;

          /**
          * 發(fā)送郵件的主界面
          */
          @GetMapping("/")
          public ModelAndView index {
          ModelAndView mv=new ModelAndView("mail/sendMail");//打開發(fā)送郵件的頁面
          mv.addObject("from", mailService.getMailSendFrom);//郵件發(fā)信人
          return mv;
          }
          /**
          * 發(fā)送郵件
          */
          @PostMapping("/mail/send")
          public MailVo sendMail(MailVo mailVo, MultipartFile[] files) {
          mailVo.setMultipartFiles(files);
          return mailService.sendMail(mailVo);//發(fā)送郵件和附件
          }
          }

          然后在/resources/views/mail目錄新建sendMail.html,具體源碼如下:

          <!DOCTYPE html>
          <html xmlns:th="http://www.thymeleaf.org">

          <head>
          <meta charset="UTF-8"/>
          <title>發(fā)送郵件</title>
          <link th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" rel="stylesheet" type="text/css"/>
          <script th:src="@{/webjars/jquery/jquery.min.js}"></script>
          <script th:href="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>

          </head>

          <body>
          <div class="col-md-6" style="margin:20px;padding:20px;border: #E0E0E0 1px solid;">
          <marquee behavior="alternate" onfinish="alert(12)" id="mq"
          onMouseOut="this.start;$('#egg').text('嗯 真聽話!');"
          onMouseOver="this.stop;$('#egg').text('有本事放開我呀!');">
          <h5 id="egg">祝大家新年快樂!</h5><img id="doge" src="http://pics.sc.chinaz.com/Files/pic/faces/3709/7.gif" alt="">
          </marquee>

          <form class="form-horizontal" id="mailForm">
          <div class="form-group">
          <label class="col-md-2 control-label">郵件發(fā)信人:</label>
          <div class="col-md-6">
          <input class="form-control" id="from" name="from" th:value="${from}" readonly="readonly">
          </div>
          </div>
          <div class="form-group">
          <label class="col-md-2 control-label">郵件收信人:</label>
          <div class="col-md-6">
          <input class="form-control" id="to" name="to" title="多個郵箱使用,隔開">
          </div>
          </div>
          <div class="form-group">
          <label class="col-md-2 control-label">郵件主題:</label>
          <div class="col-md-6">
          <input class="form-control" id="subject" name="subject">
          </div>
          </div>
          <div class="form-group">
          <label class="col-md-2 control-label">郵件內(nèi)容:</label>
          <div class="col-md-6">
          <textarea class="form-control" id="text" name="text" rows="5"></textarea>
          </div>
          </div>
          <div class="form-group">
          <label class="col-md-2 control-label">郵件附件:</label>
          <div class="col-md-6">
          <input class="form-control" id="files" name="files" type="file" multiple="multiple">
          </div>
          </div>
          <div class="form-group">
          <label class="col-md-2 control-label">郵件操作:</label>
          <div class="col-md-3">
          <a class="form-control btn btn-primary" onclick="sendMail">發(fā)送郵件</a>
          </div>
          <div class="col-md-3">
          <a class="form-control btn btn-default" onclick="clearForm">清空</a>
          </div>
          </div>
          </form>

          <script th:inline="javascript">
          var appCtx=[[${#request.getContextPath()}]];

          function sendMail {

          var formData=new FormData($('#mailForm')[0]);
          $.ajax({
          url: appCtx + '/mail/send',
          type: "POST",
          data: formData,
          contentType: false,
          processData: false,
          success: function (result) {
          alert(result.status==='ok' ? "發(fā)送成功!" : "你被Doge嘲諷了:" + result.error);
          },
          error: function {
          alert("發(fā)送失敗!");
          }
          });
          }

          function clearForm {
          $('#mailForm')[0].reset;
          }

          setInterval(function {
          var total=$('#mq').width;
          var width=$('#doge').width;
          var left=$('#doge').offset.left;
          if (left <=width / 2 + 20) {
          $('#doge').css('transform', 'rotateY(180deg)')
          }
          if (left >=total - width / 2 - 40) {
          $('#doge').css('transform', 'rotateY(-360deg)')
          }
          });
          </script>
          </div>
          </body>
          </html>

          四、測試發(fā)送郵件

          如果是初學(xué)者,建議大家先下載源碼,修改配置后運行工程,成功后再自己重新寫一遍代碼,這樣有助于加深記憶。

          啟動工程并訪問:http://localhost:8080 然后可以看到發(fā)送郵件的主界面如下:

          然后填寫你的小號郵箱,點擊發(fā)送郵件,若成功則可以登陸小號郵箱查看郵件和剛才上傳的附件。

          至此發(fā)送郵件代碼全部完成,歡迎大家下載關(guān)注Github 源碼。

          五、常見失敗編碼

          如果企業(yè)定制了郵件服務(wù)器,自然會記錄郵件日志,根據(jù)錯誤編碼存儲日志有利于日常維護。

          例如這些由網(wǎng)易郵箱提供的錯誤編碼標識:

          421

          • 421 HL:REP 該IP發(fā)送行為異常,存在接收者大量不存在情況,被臨時禁止連接。請檢查是否有用戶發(fā)送病毒或者垃圾郵件,并核對發(fā)送列表有效性;

          • 421 HL:ICC 該IP同時并發(fā)連接數(shù)過大,超過了網(wǎng)易的限制,被臨時禁止連接。請檢查是否有用戶發(fā)送病毒或者垃圾郵件,并降低IP并發(fā)連接數(shù)量;

          • 421 HL:IFC 該IP短期內(nèi)發(fā)送了大量信件,超過了網(wǎng)易的限制,被臨時禁止連接。請檢查是否有用戶發(fā)送病毒或者垃圾郵件,并降低發(fā)送頻率;

          • 421 HL:MEP 該IP發(fā)送行為異常,存在大量偽造發(fā)送域域名行為,被臨時禁止連接。請檢查是否有用戶發(fā)送病毒或者垃圾郵件,并使用真實有效的域名發(fā)送;

          450

          • 450 MI:CEL 發(fā)送方出現(xiàn)過多的錯誤指令。請檢查發(fā)信程序;

          • 450 MI:DMC 當(dāng)前連接發(fā)送的郵件數(shù)量超出限制。請減少每次連接中投遞的郵件數(shù)量;

          • 450 MI:CCL 發(fā)送方發(fā)送超出正常的指令數(shù)量。請檢查發(fā)信程序;

          • 450 RP:DRC 當(dāng)前連接發(fā)送的收件人數(shù)量超出限制。請控制每次連接投遞的郵件數(shù)量;

          • 450 RP:CCL 發(fā)送方發(fā)送超出正常的指令數(shù)量。請檢查發(fā)信程序;

          • 450 DT:RBL 發(fā)信IP位于一個或多個RBL里。請參考http://www.rbls.org/關(guān)于RBL的相關(guān)信息;

          • 450 WM:BLI 該IP不在網(wǎng)易允許的發(fā)送地址列表里;

          • 450 WM:BLU 此用戶不在網(wǎng)易允許的發(fā)信用戶列表里;

          451

          • 451 DT:SPM ,please try again 郵件正文帶有垃圾郵件特征或發(fā)送環(huán)境缺乏規(guī)范性,被臨時拒收。請保持郵件隊列,兩分鐘后重投郵件。需調(diào)整郵件內(nèi)容或優(yōu)化發(fā)送環(huán)境;

          • 451 Requested mail action not taken: too much fail authentication 登錄失敗次數(shù)過多,被臨時禁止登錄。請檢查密碼與帳號驗證設(shè)置;

          • 451 RP:CEL 發(fā)送方出現(xiàn)過多的錯誤指令。請檢查發(fā)信程序;

          • 451 MI:DMC 當(dāng)前連接發(fā)送的郵件數(shù)量超出限制。請控制每次連接中投遞的郵件數(shù)量;

          • 451 MI:SFQ 發(fā)信人在15分鐘內(nèi)的發(fā)信數(shù)量超過限制,請控制發(fā)信頻率;

          • 451 RP:QRC 發(fā)信方短期內(nèi)累計的收件人數(shù)量超過限制,該發(fā)件人被臨時禁止發(fā)信。請降低該用戶發(fā)信頻率;

          • 451 Requested action aborted: local error in processing 系統(tǒng)暫時出現(xiàn)故障,請稍后再次嘗試發(fā)送;

          500

          • 500 Error: bad syntaxU 發(fā)送的smtp命令語法有誤;

          • 550 MI:NHD HELO命令不允許為空;

          • 550 MI:IMF 發(fā)信人電子郵件地址不合規(guī)范。請參考http://www.rfc-editor.org/關(guān)于電子郵件規(guī)范的定義;

          • 550 MI:SPF 發(fā)信IP未被發(fā)送域的SPF許可。請參考http://www.openspf.org/關(guān)于SPF規(guī)范的定義;

          • 550 MI:DMA 該郵件未被發(fā)信域的DMARC許可。請參考http://dmarc.org/關(guān)于DMARC規(guī)范的定義;

          • 550 MI:STC 發(fā)件人當(dāng)天的連接數(shù)量超出了限定數(shù)量,當(dāng)天不再接受該發(fā)件人的郵件。請控制連接次數(shù);

          • 550 RP:FRL 網(wǎng)易郵箱不開放匿名轉(zhuǎn)發(fā)(Open relay);

          • 550 RP:RCL 群發(fā)收件人數(shù)量超過了限額,請減少每封郵件的收件人數(shù)量;

          • 550 RP:TRC 發(fā)件人當(dāng)天內(nèi)累計的收件人數(shù)量超過限制,當(dāng)天不再接受該發(fā)件人的郵件。請降低該用戶發(fā)信頻率;

          • 550 DT:SPM 郵件正文帶有很多垃圾郵件特征或發(fā)送環(huán)境缺乏規(guī)范性。需調(diào)整郵件內(nèi)容或優(yōu)化發(fā)送環(huán)境;

          • 550 Invalid User 請求的用戶不存在;

          • 550 User in blacklist 該用戶不被允許給網(wǎng)易用戶發(fā)信;

          • 550 User suspended 請求的用戶處于禁用或者凍結(jié)狀態(tài);

          • 550 Requested mail action not taken: too much recipient 群發(fā)數(shù)量超過了限額;

          552

          • 552 Illegal Attachment 不允許發(fā)送該類型的附件,包括以.uu .pif .scr .mim .hqx .bhx .cmd .vbs .bat .com .vbe .vb .js .wsh等結(jié)尾的附件;

          • 552 Requested mail action aborted: exceeded mailsize limit 發(fā)送的信件大小超過了網(wǎng)易郵箱允許接收的最大限制;

          553

          • 553 Requested action not taken: sender is not allowed 不允許發(fā)件人為空,請使用真實發(fā)件人發(fā)送;

          • 553 Requested action not taken: Local user only SMTP類型的機器只允許發(fā)信人是本站用戶;

          • 553 Requested action not taken: no smtp MX only MX類型的機器不允許發(fā)信人是本站用戶;

          • 553 authentication is required SMTP需要身份驗證,請檢查客戶端設(shè)置;

          554

          • 554 DT:SPM 發(fā)送的郵件內(nèi)容包含了未被許可的信息,或被系統(tǒng)識別為垃圾郵件。請檢查是否有用戶發(fā)送病毒或者垃圾郵件;

          • 554 DT:SUM 信封發(fā)件人和信頭發(fā)件人不匹配;

          • 554 IP is rejected, smtp auth error limit exceed 該IP驗證失敗次數(shù)過多,被臨時禁止連接。請檢查驗證信息設(shè)置;

          • 554 HL:IHU 發(fā)信IP因發(fā)送垃圾郵件或存在異常的連接行為,被暫時掛起。請檢測發(fā)信IP在歷史上的發(fā)信情況和發(fā)信程序是否存在異常;

          • 554 HL:IPB 該IP不在網(wǎng)易允許的發(fā)送地址列表里;

          • 554 MI:STC 發(fā)件人當(dāng)天內(nèi)累計郵件數(shù)量超過限制,當(dāng)天不再接受該發(fā)件人的投信。請降低發(fā)信頻率;

          • 554 MI:SPB 此用戶不在網(wǎng)易允許的發(fā)信用戶列表里;

          • 554 IP in blacklist 該IP不在網(wǎng)易允許的發(fā)送地址列表里。

          【END】

          Low了,網(wǎng)頁居然還用這么老掉牙的特效!弄個粗體字,下劃線就是突出重點了?真是一股濃濃的鄉(xiāng)村風(fēng)撲面而來;弄個圖在頁面飄來飄去就是動畫效果了,你要這么認為的話那我只能保持沉默了。在HTML5占領(lǐng)著整個互聯(lián)網(wǎng)之時,想透過網(wǎng)頁抓住所有人的眼球,因循守舊是行不通的。因此,有你不能不知道的HTML常用代碼。只有熟悉掌握了常用的HTML代碼,你才能在編寫網(wǎng)頁的時候做到行云流水,用處處流露著細膩和創(chuàng)意的動效細節(jié)打動所有人。

          在這里還是要說一下我自己建的前端JavaScript學(xué)習(xí)交流群:574462090,不管你是小白還是大牛,小編我都挺歡迎,小白嘛,多問點問題也就學(xué)好了,不定期分享干貨,包括最新的2017年前端學(xué)習(xí)資料,歡迎初學(xué)和進階中的小伙伴。

          html代碼大全:結(jié)構(gòu)性定義

          文件類型<HTML></HTML> (放在檔案的開頭與結(jié)尾)

          文件主題<TITLE></TITLE> (必須放在「文頭」區(qū)塊內(nèi))

          文頭<HEAD></HEAD> (描述性資料,像是「主題」)

          文體<BODY></BODY> (文件本體)

          標題<H?></H?> (從1到6,有六層選擇)

          標題的對齊 <H?ALIGN=LEFT|CENTER|RIGHT></H?>

          區(qū)分<DIV></DIV>

          區(qū)分的對齊 <DIVALIGN=LEFT|RIGHT|CENTER|JUSTIFY></DIV>

          引文區(qū)塊<BLOCKQUOTE></BLOCKQUOTE> (通常會內(nèi)縮)

          強調(diào)<EM></EM> (通常會以斜體顯示)

          特別強調(diào)<STRONG></STRONG> (通常會以加粗顯示)

          引文<CITE></CITE> (通常會以斜體顯示)

          碼<CODE></CODE> (顯示原始碼之用)

          樣本<SAMP></SAMP>

          鍵盤輸入<KBD></KBD>

          變數(shù)<VAR></VAR>

          定義<DFN></DFN> (有些瀏覽器不提供)

          地址 <ADDRESS></ADDRESS>

          大字<BIG></BIG>

          小字<SMALL></SMALL>

          與外觀相關(guān)的標簽(作者自訂的表現(xiàn)方式)

          加粗<B></B>

          斜體<I></I>

          底線<U></U> (尚有些瀏覽器不提供)

          刪除線<S></S> (尚有些瀏覽器不提供)

          下標<SUB></SUB>

          上標<SUP></SUP>

          打字機體<TT></TT> (用單空格字型顯示)

          預(yù)定格式<PRE></PRE> (保留文件中空格的大小)

          預(yù)定格式的寬度<PRE WIDTH=?></PRE>(以字元計算)

          向中看齊<CENTER></CENTER> (文字與圖片都可以)

          閃耀<BLINK></BLINK> (有史以來最被嘲弄的標簽)

          字體大小 <FONTSIZE=?></FONT>(從1到7)

          改變字體大小 <FONTSIZE=+|-?></FONT>

          基本字體大小 <BASEFONTSIZE=?> (從1到7; 內(nèi)定為3)

          字體顏色 <FONTCOLOR="#$$"></FONT>($$為顏色代碼)

          2

          html代碼大全:修改頁面的實用性HTML代碼

          1)貼圖:<img src="圖片地址">

          2)加入連接:<a href="所要連接的相關(guān)地址">寫上你想寫的字</a>

          3)在新窗口打開連接:<a href="相關(guān)地址" target="_blank">寫上要寫的字</a>

          4)移動字體(走馬燈):<marquee>寫上你想寫的字</marquee>

          5)字體加粗:<b>寫上你想寫的字</b>

          6)字體斜體:<i>寫上你想寫的字</i>

          7)字體下劃線: <u>寫上你想寫的字</u>

          8)字體刪除線: <s>寫上你想寫的字</s>

          9)字體加大: <big>寫上你想寫的字</big>

          10)字體控制大小:<h1>寫上你想寫的字</h1> (其中字體大小可從h1-h5,h1最大,h5最小)

          11)更改字體顏色:<font color="#value">寫上你想寫的字</font>(其中value值在000000與ffffff(16位進制)之間

          12)消除連接的下劃線:<a href="相關(guān)地址" style="text-decoration:none">寫上你想寫的字</a>

          13)貼音樂:<embed src="音樂地址" width="寬度" height="高度" autostart=false>

          14)貼flash: <embed src="flash地址" width="寬度" height="高度">

          15)貼影視文件:<img dynsrc="文件地址" width="寬度" height="高度" start=mouseover>

          16)換行:<br>

          17)段落:<p>段落</p>

          18)原始文字樣式:<pre>正文</pre>

          19)換帖子背景:<body background="背景圖片地址">

          20)固定帖子背景不隨滾動條滾動:<body background="背景圖片地址" body

          bgproperties=fixed>

          21)定制帖子背景顏色:<body bgcolor="#value">(value值見10)

          22)帖子背景音樂:<bgsound="背景音樂地址" loop=infinite>

          23)貼網(wǎng)頁:<iframe. src="相關(guān)地址" width="寬度" height="高度"></iframe>

          3

          html代碼大全:常常會遇到的問題

          點擊關(guān)閉窗口

          <a href="javascript.:top.window.close();">點擊關(guān)閉窗口</a>!

          請問如何去掉主頁右面的滾動條?

          <body scroll="no">

          <body style="overflow-y:hidden">

          如何做到讓一個網(wǎng)頁自動關(guān)閉.

          <html>

          <head>

          <OBJECT id=closes type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">

          <param name="Command" value="Close">

          </object>

          </head>

          <body >

          這個窗口會在10秒過后自動關(guān)閉,而且不會出現(xiàn)提示. </body>

          如何在不刷新頁面的情況下刷新css?

          <style>

          button{ color:#000000;}

          </style>

          <button nclick=document.styleSheets[0].rules[0].style.color=‘‘‘‘red‘‘‘‘>點擊按鈕直接修改style標簽里button選擇符使按鈕改為  紅色</button>

          請問如何讓網(wǎng)頁自動刷新?

          在head部記入<META. HTTP-EQUIV="Refresh" c>其中20為20秒后自動刷新,你可以更改為任意值。

          如何讓頁面自動刷新?

          方法一,用refresh

          HTML 代碼片段如下:

          <head>

          <meta. http-equiv="refresh" c>

          </head>

          5表示刷新時間

          [Ctrl+A 全部選擇 提示:你可先修改部分代碼,再按運行]

          方法二,使用setTimeout控制

          <img src=/logo.gif>

          <script>

          function rl(){

          document.location.reload()

          }

          setTimeout(rl,2000)

          </SCRIPT>

          如何讓超鏈接沒有下劃線

          在源代碼中的<HEAD>…</HEAD>之間輸入如下代碼:

          <style. type="text/css"> <!--

          a { text-decoration: none}

          --> </style>

          請問如何去掉IE的上下滾動條?

          <body style=‘‘‘‘overflow:scroll;overflow-y:hidden‘‘‘‘>

          </body>

          怎樣才能把RealPlayer文件在網(wǎng)頁做一個試聽連接?

          <embed height=25 src=51js.rm type=audio/x-pn-realaudio-plugin width=50 autostart="false" c>

          如何用html實現(xiàn)瀏覽器上后退按鈕的功能?

          <a href="java script.:history.go(-1)">點擊后退</a>

          或者

          <script> history.back() </SCRIPT>

          4

          html代碼大全:你不一定知道的技巧

          16. ncontextmenu="window.event.returnValue=false" 將徹底屏蔽鼠標右鍵

            <table borderncontextmenu=return(false)><td>no</table> 可用于Table

          17. <body nselectstart="return false"> 取消選取、防止復(fù)制

          18.onpaste="return false" 不準粘貼

          19.oncopy="return false;" ncut="return false;" 防止復(fù)制

          20. <link rel="Shortcut Icon"href="favicon.ico"> IE地址欄前換成自己的圖標

          21. <link rel="Bookmark"href="favicon.ico"> 可以在收藏夾中顯示出你的圖標

          22. <inputstyle="ime-mode:disabled"> 關(guān)閉輸入法

          23. 永遠都會帶著框架

          <script. language="JavaScript"><!--

          if (window==top)top.location.href="frames.htm"; //frames.htm為框架網(wǎng)頁

          // --></script>

          24. 防止被人frame.

          <SCRIPT. LANGUAGE=JAVASCRIPT><!--

          if (top.location !=self.location)top.location=self.location;

          // --></SCRIPT>

          25. 網(wǎng)頁將不能被另存為

          <noscript><iframe.src=*.html></iframe></noscript>

          26. 查看網(wǎng)頁源代碼

          <input type=button value=查看網(wǎng)頁源代碼

          onclick="window.location="view-source:"+"http://www.pconline.com.cn"">

          27.刪除時確認

          <a href="javascript:if(confirm("確實要刪除嗎?"))location="boos.asp? &areyou=刪除&page=1"">刪除</a>

          28.屏蔽功能鍵Shift,Alt,Ctrl

          <script>

          function look(){

          if(event.shiftKey)

          alert("禁止按Shift鍵!");//可以換成ALT CTRL

          }

          document.onkeydown=look;

          </script>

          29. 網(wǎng)頁不會被緩存

          <META. HTTP-EQUIV="pragma" CONTENT="no-cache">

          <META. HTTP-EQUIV="Cache-Control"CONTENT="no-cache, must-revalidate">

          <META. HTTP-EQUIV="expires"CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">

          或者<META. HTTP-EQUIV="expires"CONTENT="0">

          30.怎樣讓表單沒有凹凸感?

          <input type=text style="border:1 solid #000000">

          或 <input type=text style="border-left:none;border-right:none; border -top:none; border-bottom: 1 solid#000000"></textarea>

          31.不要滾動條?

          讓豎條沒有:

          <body style="overflow:scroll;overflow-y:hidden">

          </body>

          讓橫條沒有:

          <body style="overflow:scroll;overflow-x:hidden">

          </body>

          兩個都去掉?更簡單了

          <body scroll="no">

          </body>

          32.怎樣去掉圖片鏈接點擊后,圖片周圍的虛線?

          <a href="#"nFocus="this.blur()"><img src="logo.jpg"border=0></a>

          33.電子郵件處理提交表單

          <form. name="form1"method="post" action="mailt****@***.com"enctype="text/plain">

          <input type=submit>

          </form>

          34.在打開的子窗口刷新父窗口的代碼里如何寫?

          window.opener.location.reload()

          35.如何設(shè)定打開頁面的大小

          <body nload="top.resizeTo(300,200);">

          打開頁面的位置<bodynload="top.moveBy(300,200);">

          36.在頁面中如何加入不是滿鋪的背景圖片,拉動頁面時背景圖不動

          <STYLE>

          body

          {background-image:url(logo.gif); background-repeat:no-repeat;

          background-position:center;background-attachment: fixed}

          </STYLE>

          37. 檢查一段字符串是否全由數(shù)字組成

          <script. language="Javascript"><!--

          function checkNum(str){return str.match(//D/)==null}

          alert(checkNum("1232142141"))

          alert(checkNum("123214214a1"))

          // --></script>

          38. 獲得一個窗口的大小

          document.body.clientWidth; document.body.clientHeight

          39. 怎么判斷是否是字符

          if (/[^/x00-/xff]/g.test(s)) alert("含有漢字");

          else alert("全是字符");

          40.TEXTAREA自適應(yīng)文字行數(shù)的多少

          <textarea rows=1 name=s1 cols=27npropertychange="this.style.posHeight=this.scrollHeight">

          </textarea>

          41. 日期減去天數(shù)等于第二個日期

          <script. language=Javascript>

          function cc(dd,dadd)

          {

          //可以加上錯誤處理

          var a=new Date(dd)

          a=a.valueOf()

          a=a - dadd * 24 * 60 * 60 * 1000

          a=new Date(a)

          alert(a.getFullYear() + "年" + (a.getMonth() +1) + "月" + a.getDate() + "日")

          } cc("12/23/2002",2)

          </script>

          42. 選擇了哪一個Radio

          <HTML><script. language="vbscript">

          function checkme()

          for each ob in radio1

          if ob.checked then window.alert ob.value

          next

          end function

          </script><BODY>

          <INPUT name="radio1" type="radio"value="style" checked>Style.

          <INPUT name="radio1" type="radio"value="barcode">Barcode

          <INPUT type="button" value="check"nclick="checkme()">

          </BODY></HTML>

          43.腳本永不出錯

          <SCRIPT. LANGUAGE="JavaScript">

          <!-- Hide function killErrors(){return true;} window.onerror=killErrors;// -->

          </SCRIPT>

          44.ENTER鍵可以讓光標移到下一個輸入框

          <input nkeydown="if(event.keyCode==13)event.keyCode=9">

          文末再提兩點建議吧:

          1. 剛學(xué)前端JavaScript的時候,一定不要追求速成,編程不比其他傳統(tǒng)行業(yè),可以快速的上手,他需要一定的代碼量積累起來,不然你追求速成很可能會車毀人亡。

          2. 這個文章到這里就說完了,想要前端學(xué)習(xí)資料的進我的群自助領(lǐng)取,已經(jīng)上傳到群文件里了:574462090,歡迎初學(xué)和進階中的小伙伴。

          如果想看到更加系統(tǒng)的文章和學(xué)習(xí)方法經(jīng)驗可以關(guān)注我的微信公眾號:‘前端根據(jù)地’關(guān)注后回復(fù)‘給我資料’可以領(lǐng)取一套完整的學(xué)習(xí)視頻


          主站蜘蛛池模板: 99国产精品一区二区| 亚洲一本一道一区二区三区| 中文字幕日韩一区二区三区不| 一区二区三区内射美女毛片| 老熟妇仑乱视频一区二区| 亚洲av成人一区二区三区观看在线| 亚洲熟妇成人精品一区| 视频一区在线免费观看| 国产欧美一区二区精品仙草咪| 亚洲AV综合色区无码一区爱AV| 视频一区二区精品的福利| 大香伊蕉日本一区二区| 亚洲Av高清一区二区三区| 无码一区二区三区老色鬼| 日韩制服国产精品一区| 香蕉久久AⅤ一区二区三区| 无码一区二区三区免费视频| 亚洲国产情侣一区二区三区| 久久国产一区二区三区| 国产精品一区二区三区免费| 精品视频一区二区观看| 国产福利在线观看一区二区| 国产一区二区在线观看视频| 国产精品亚洲综合一区在线观看 | 成人区人妻精品一区二区不卡| 中文字幕视频一区| 亚洲日本一区二区三区| 人妻AV一区二区三区精品 | 亚洲国产精品一区二区第四页| 精品国产福利在线观看一区| 韩国精品一区视频在线播放| 日韩福利视频一区| 日本强伦姧人妻一区二区| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 中日韩精品无码一区二区三区| 国产精品自拍一区| 免费看AV毛片一区二区三区| 视频精品一区二区三区| 中文字幕亚洲一区| 亚洲一区二区三区在线观看蜜桃 | 91福利视频一区|