整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          springboot整合郵件服務超詳細教程

          springboot整合郵件服務超詳細教程

          者:yizhiwazi

          www.jianshu.com/p/5eb000544dd7

          基礎知識

          什么是SMTP?

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

          什么是IMAP?

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

          什么是POP3?

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

          IMAP和POP3協議有什么不同呢?

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

          進階知識

          什么是JavaMailSender和JavaMailSenderImpl?

          JavaMailSender和JavaMailSenderImpl 是Spring官方提供的集成郵件服務的接口和實現類,以簡單高效的設計著稱,目前是Java后端發送郵件和集成郵件服務的主流工具。

          如何通過JavaMailSenderImpl發送郵件?

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

              @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);
          
                  //復雜郵件
                  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 能夠開箱即用 ?

          所謂開箱即用其實就是基于官方內置的自動配置,翻看源碼可知曉郵件自動配置類(MailSenderPropertiesConfiguration) 為上下文提供了郵件服務實例(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是關于郵件服務器的配置信息,具體源碼如下:

          @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<>();
          }

          使用教程

          一、開啟郵件服務

          登陸網易郵箱163,在設置中打開并勾選POP3/SMTP/IMAP服務,然后會得到一個授權碼,這個郵箱和授權碼將用作登陸認證。

          二、配置郵件服務

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

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

              <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>

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

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

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

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

          那么優雅的發送郵件應該是如何的呢?應該屏蔽掉這些構建信息和發送郵件的細節,不管是簡單還是復雜郵件,都可以通過統一的API來發送郵件。例如:mailService.send(mailVo) 。

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

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

          三、發送郵件和附件

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

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

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

          本案例郵件業務類 MailService 的具體源碼如下:

          package com.hehe.service;
          
          /**
           * 郵件業務類 MailService
           */
          @Service
          public class MailService {
          
              private Logger logger = LoggerFactory.getLogger(getClass());//提供日志類
          
              @Autowired
              private JavaMailSenderImpl mailSender;//注入郵件工具類
          
          
              /**
               * 發送郵件
               */
              public MailVo sendMail(MailVo mailVo) {
                  try {
                      checkMail(mailVo); //1.檢測郵件
                      sendMimeMail(mailVo); //2.發送郵件
                      return saveMail(mailVo); //3.保存郵件
                  } catch (Exception e) {
                      logger.error("發送郵件失敗:", 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("郵件內容不能為空");
                  }
              }
          
              //構建復雜郵件信息類
              private void sendMimeMail(MailVo mailVo) {
                  try {
                      MimeMessageHelper messageHelper = new MimeMessageHelper(mailSender.createMimeMessage(), true);//true表示支持復雜類型
                      mailVo.setFrom(getMailSendFrom());//郵件發信人從配置項讀取
                      messageHelper.setFrom(mailVo.getFrom());//郵件發信人
                      messageHelper.setTo(mailVo.getTo().split(","));//郵件收信人
                      messageHelper.setSubject(mailVo.getSubject());//郵件主題
                      messageHelper.setText(mailVo.getText());//郵件內容
                      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())) {//發送時間
                          mailVo.setSentDate(new Date());
                          messageHelper.setSentDate(mailVo.getSentDate());
                      }
                      mailSender.send(messageHelper.getMimeMessage());//正式發送郵件
                      mailVo.setStatus("ok");
                      logger.info("發送郵件成功:{}->{}", mailVo.getFrom(), mailVo.getTo());
                  } catch (Exception e) {
                      throw new RuntimeException(e);//發送失敗
                  }
              }
          
              //保存郵件
              private MailVo saveMail(MailVo mailVo) {
                  //將郵件保存到數據庫..
                  return mailVo;
              }
          
              //獲取郵件發信人
              public String getMailSendFrom() {
                  return mailSender.getJavaMailProperties().getProperty("from");
              }
          }

          搞定了發送郵件最核心的業務邏輯,接下來咱們寫一個簡單頁面用來發送郵件。

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

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

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

          <!DOCTYPE html>
          <html xmlns:th="http://www.thymeleaf.org">
          
          <head>
              <meta charset="UTF-8"/>
              <title>發送郵件</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">郵件發信人:</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">郵件內容:</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()">發送郵件</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' ? "發送成功!" : "你被Doge嘲諷了:" + result.error);
                          },
                          error: function () {
                              alert("發送失敗!");
                          }
                      });
                  }
          
                  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>

          四、測試發送郵件

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

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

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

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

          五、常見失敗編碼

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

          例如這些由網易郵箱提供的錯誤編碼標識:

          421

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

          450

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

          451

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

          500

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

          552

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

          553

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

          554

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

          質文章,及時送達

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

          基礎知識

          什么是SMTP?

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

          什么是IMAP?

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

          什么是POP3?

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

          IMAP和POP3協議有什么不同呢?

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

          進階知識

          什么是JavaMailSender和JavaMailSenderImpl?

          JavaMailSender和JavaMailSenderImpl 是Spring官方提供的集成郵件服務的接口和實現類,以簡單高效的設計著稱,目前是Java后端發送郵件和集成郵件服務的主流工具。

          如何通過JavaMailSenderImpl發送郵件?

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

          @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);

          //復雜郵件
          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 能夠開箱即用 ?

          所謂開箱即用其實就是基于官方內置的自動配置,翻看源碼可知曉郵件自動配置類(MailSenderPropertiesConfiguration) 為上下文提供了郵件服務實例(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是關于郵件服務器的配置信息,具體源碼如下:

          @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<>;
          }

          使用教程

          一、開啟郵件服務

          登陸網易郵箱163,在設置中打開并勾選POP3/SMTP/IMAP服務,然后會得到一個授權碼,這個郵箱和授權碼將用作登陸認證。

          二、配置郵件服務

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

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

          <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>

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

          Tips:關注微信公眾號:Java后端,每日提送技術博文。

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

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

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

          那么優雅的發送郵件應該是如何的呢?應該屏蔽掉這些構建信息和發送郵件的細節,不管是簡單還是復雜郵件,都可以通過統一的API來發送郵件。例如:mailService.send(mailVo) 。

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

          package com.hehe.vo;

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

          三、發送郵件和附件

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

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

          • 發送郵件 sendMimeMail; 其次通過MimeMessageHelper來解析MailVo并構建MimeMessage傳輸郵件。

          • 保存郵件 sendMimeMail; 最后將郵件保存到數據庫,便于統計和追查郵件問題。

          本案例郵件業務類 MailService 的具體源碼如下:

          package com.hehe.service;

          /**
          * 郵件業務類 MailService
          */
          @Service
          publicclassMailService{

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

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


          /**
          * 發送郵件
          */
          public MailVo sendMail(MailVo mailVo) {
          try {
          checkMail(mailVo); //1.檢測郵件
          sendMimeMail(mailVo); //2.發送郵件
          return saveMail(mailVo); //3.保存郵件
          } catch (Exception e) {
          logger.error("發送郵件失敗:", 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("郵件內容不能為空");
          }
          }

          //構建復雜郵件信息類
          privatevoidsendMimeMail(MailVo mailVo) {
          try {
          MimeMessageHelper messageHelper=new MimeMessageHelper(mailSender.createMimeMessage, true);//true表示支持復雜類型
          mailVo.setFrom(getMailSendFrom);//郵件發信人從配置項讀取
          messageHelper.setFrom(mailVo.getFrom);//郵件發信人
          messageHelper.setTo(mailVo.getTo.split(","));//郵件收信人
          messageHelper.setSubject(mailVo.getSubject);//郵件主題
          messageHelper.setText(mailVo.getText);//郵件內容
          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)) {//發送時間
          mailVo.setSentDate(new Date);
          messageHelper.setSentDate(mailVo.getSentDate);
          }
          mailSender.send(messageHelper.getMimeMessage);//正式發送郵件
          mailVo.setStatus("ok");
          logger.info("發送郵件成功:{}->{}", mailVo.getFrom, mailVo.getTo);
          } catch (Exception e) {
          throw new RuntimeException(e);//發送失敗
          }
          }

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

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

          搞定了發送郵件最核心的業務邏輯,接下來咱們寫一個簡單頁面用來發送郵件。

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

          @RestController
          publicclassMailController{
          @Autowired
          private MailService mailService;

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

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

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

          <head>
          <meta charset="UTF-8"/>
          <title>發送郵件</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">郵件發信人:</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">郵件內容:</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">發送郵件</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' ? "發送成功!" : "你被Doge嘲諷了:" + result.error);
          },
          error: function {
          alert("發送失敗!");
          }
          });
          }

          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>

          四、測試發送郵件

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

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

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

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

          五、常見失敗編碼

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

          例如這些由網易郵箱提供的錯誤編碼標識:

          421

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

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

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

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

          450

          • 450 MI:CEL 發送方出現過多的錯誤指令。請檢查發信程序;

          • 450 MI:DMC 當前連接發送的郵件數量超出限制。請減少每次連接中投遞的郵件數量;

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

          • 450 RP:DRC 當前連接發送的收件人數量超出限制。請控制每次連接投遞的郵件數量;

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

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

          • 450 WM:BLI 該IP不在網易允許的發送地址列表里;

          • 450 WM:BLU 此用戶不在網易允許的發信用戶列表里;

          451

          • 451 DT:SPM ,please try again 郵件正文帶有垃圾郵件特征或發送環境缺乏規范性,被臨時拒收。請保持郵件隊列,兩分鐘后重投郵件。需調整郵件內容或優化發送環境;

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

          • 451 RP:CEL 發送方出現過多的錯誤指令。請檢查發信程序;

          • 451 MI:DMC 當前連接發送的郵件數量超出限制。請控制每次連接中投遞的郵件數量;

          • 451 MI:SFQ 發信人在15分鐘內的發信數量超過限制,請控制發信頻率;

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

          • 451 Requested action aborted: local error in processing 系統暫時出現故障,請稍后再次嘗試發送;

          500

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

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

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

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

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

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

          • 550 RP:FRL 網易郵箱不開放匿名轉發(Open relay);

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

          • 550 RP:TRC 發件人當天內累計的收件人數量超過限制,當天不再接受該發件人的郵件。請降低該用戶發信頻率;

          • 550 DT:SPM 郵件正文帶有很多垃圾郵件特征或發送環境缺乏規范性。需調整郵件內容或優化發送環境;

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

          • 550 User in blacklist 該用戶不被允許給網易用戶發信;

          • 550 User suspended 請求的用戶處于禁用或者凍結狀態;

          • 550 Requested mail action not taken: too much recipient 群發數量超過了限額;

          552

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

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

          553

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

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

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

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

          554

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

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

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

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

          • 554 HL:IPB 該IP不在網易允許的發送地址列表里;

          • 554 MI:STC 發件人當天內累計郵件數量超過限制,當天不再接受該發件人的投信。請降低發信頻率;

          • 554 MI:SPB 此用戶不在網易允許的發信用戶列表里;

          • 554 IP in blacklist 該IP不在網易允許的發送地址列表里。

          【END】

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

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

          html代碼大全:結構性定義

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

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

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

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

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

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

          區分<DIV></DIV>

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

          引文區塊<BLOCKQUOTE></BLOCKQUOTE> (通常會內縮)

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

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

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

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

          樣本<SAMP></SAMP>

          鍵盤輸入<KBD></KBD>

          變數<VAR></VAR>

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

          地址 <ADDRESS></ADDRESS>

          大字<BIG></BIG>

          小字<SMALL></SMALL>

          與外觀相關的標簽(作者自訂的表現方式)

          加粗<B></B>

          斜體<I></I>

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

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

          下標<SUB></SUB>

          上標<SUP></SUP>

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

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

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

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

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

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

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

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

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

          2

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

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

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

          3)在新窗口打開連接:<a href="相關地址" 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="相關地址" 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)貼網頁:<iframe. src="相關地址" width="寬度" height="高度"></iframe>

          3

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

          點擊關閉窗口

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

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

          <body scroll="no">

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

          如何做到讓一個網頁自動關閉.

          <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秒過后自動關閉,而且不會出現提示. </body>

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

          <style>

          button{ color:#000000;}

          </style>

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

          請問如何讓網頁自動刷新?

          在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文件在網頁做一個試聽連接?

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

          如何用html實現瀏覽器上后退按鈕的功能?

          <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"> 取消選取、防止復制

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

          19.oncopy="return false;" ncut="return false;" 防止復制

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

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

          22. <inputstyle="ime-mode:disabled"> 關閉輸入法

          23. 永遠都會帶著框架

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

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

          // --></script>

          24. 防止被人frame.

          <SCRIPT. LANGUAGE=JAVASCRIPT><!--

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

          // --></SCRIPT>

          25. 網頁將不能被另存為

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

          26. 查看網頁源代碼

          <input type=button value=查看網頁源代碼

          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. 網頁不會被緩存

          <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.如何設定打開頁面的大小

          <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. 檢查一段字符串是否全由數字組成

          <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自適應文字行數的多少

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

          </textarea>

          41. 日期減去天數等于第二個日期

          <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. 剛學前端JavaScript的時候,一定不要追求速成,編程不比其他傳統行業,可以快速的上手,他需要一定的代碼量積累起來,不然你追求速成很可能會車毀人亡。

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

          如果想看到更加系統的文章和學習方法經驗可以關注我的微信公眾號:‘前端根據地’關注后回復‘給我資料’可以領取一套完整的學習視頻


          主站蜘蛛池模板: 香蕉久久一区二区不卡无毒影院 | 国产精品亚洲一区二区麻豆| 亚洲福利一区二区| 日本精品一区二区久久久| 色欲综合一区二区三区| 日本免费一区二区三区最新vr| 一区二区免费视频| 国产AV午夜精品一区二区三区| 国产一区二区三区露脸| 亚洲熟女综合色一区二区三区| 午夜福利一区二区三区在线观看| 国产美女口爆吞精一区二区| 日韩在线视频一区二区三区| 亚洲国产情侣一区二区三区| 精品国产福利第一区二区三区| 国产情侣一区二区三区| 无码AV一区二区三区无码| 在线观看国产一区二区三区| 国产福利酱国产一区二区| 亚洲色精品三区二区一区| 免费无码毛片一区二区APP| 国产人妖视频一区二区| 国产在线视频一区| 日韩一本之道一区中文字幕| 国产精品小黄鸭一区二区三区 | 中文无码AV一区二区三区| 韩国福利视频一区二区| 尤物精品视频一区二区三区 | 91久久精品午夜一区二区| 久久se精品一区精品二区| 好看的电影网站亚洲一区| 一区二区三区在线免费看| 久久久久人妻一区精品性色av| 久久se精品一区二区国产| 文中字幕一区二区三区视频播放| 无码精品人妻一区二区三区漫画| 无码视频一区二区三区在线观看 | 亚洲av成人一区二区三区 | 无码少妇一区二区浪潮免费| 一区二区三区视频在线观看| 久久久老熟女一区二区三区|