View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.net.smtp;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.fail;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  
24  import java.text.ParseException;
25  import java.text.SimpleDateFormat;
26  import java.util.Date;
27  import java.util.Locale;
28  import java.util.regex.Matcher;
29  import java.util.regex.Pattern;
30  
31  import org.junit.Before;
32  import org.junit.Test;
33  
34  /**
35   * Tests {@link SimpleSMTPHeader}.
36   */
37  public class SimpleSMTPHeaderTestCase {
38  
39      private Date beforeDate;
40  
41      /** Returns the msg without a date. */
42      private String checkDate(final String msg) {
43          final Pattern pat = Pattern.compile("^(Date: (.+))$", Pattern.MULTILINE);
44          final Matcher m = pat.matcher(msg);
45          if (m.find()) {
46              final String date = m.group(2);
47              final String pattern = "EEE, dd MMM yyyy HH:mm:ss Z"; // Fri, 21 Nov 1997 09:55:06 -0600
48              final SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.ENGLISH);
49              try {
50                  final Date sentDate = format.parse(date);
51                  // Round to nearest second because the text format does not include ms
52                  final long sentSecs = sentDate.getTime() / 1000;
53                  final long beforeDateSecs = beforeDate.getTime() / 1000;
54                  final Date afterDate = new Date();
55                  final long afterDateSecs = afterDate.getTime() / 1000;
56                  if (sentSecs < beforeDateSecs) {
57                      fail(sentDate + " should be after " + beforeDate);
58                  }
59                  if (sentSecs > afterDateSecs) {
60                      fail(sentDate + " should be before " + afterDate);
61                  }
62              } catch (final ParseException e) {
63                  fail("" + e);
64              }
65  
66              final int start = m.start(1);
67              final int end = m.end(1);
68              if (start == 0) {
69                  return msg.substring(end + 1);
70              }
71              return msg.substring(0, start) + msg.substring(end + 1);
72          }
73          fail("Expecting Date header in " + msg);
74          return null;
75      }
76  
77      @Before
78      public void setUp() {
79          beforeDate = new Date();
80      }
81  
82      @Test
83      public void testToString() {
84          // Note that the DotTerminatedMessageWriter converts LF to CRLF
85          final SimpleSMTPHeader header = new SimpleSMTPHeader("from@here.invalid", "to@there.invalid", "Test email");
86          assertEquals("From: from@here.invalid\nTo: to@there.invalid\nSubject: Test email\n\n", checkDate(header.toString()));
87      }
88  
89      @Test
90      public void testToStringAddHeader() {
91          final SimpleSMTPHeader header = new SimpleSMTPHeader("from@here.invalid", null, null);
92          assertNotNull(header);
93          header.addHeaderField("X-Header1", "value 1");
94          header.addHeaderField("X-Header2", "value 2");
95          // Note that the DotTerminatedMessageWriter converts LF to CRLF
96          assertEquals("X-Header1: value 1\nX-Header2: value 2\nFrom: from@here.invalid\n\n", checkDate(header.toString()));
97      }
98  
99      @Test
100     public void testToStringAddHeaderDate() {
101         final SimpleSMTPHeader header = new SimpleSMTPHeader("from@here.invalid", null, null);
102         assertNotNull(header);
103         header.addHeaderField("Date", "dummy date");
104         // does not replace the Date field
105         assertEquals("Date: dummy date\nFrom: from@here.invalid\n\n", header.toString());
106     }
107 
108     @Test
109     public void testToStringNoFrom() {
110         assertThrows(IllegalArgumentException.class, () -> new SimpleSMTPHeader(null, null, null));
111     }
112 
113     @Test
114     public void testToStringNoSubject() {
115         final SimpleSMTPHeader header = new SimpleSMTPHeader("from@here.invalid", "to@there.invalid", null);
116         assertNotNull(header);
117         // Note that the DotTerminatedMessageWriter converts LF to CRLF
118         assertEquals("From: from@here.invalid\nTo: to@there.invalid\n\n", checkDate(header.toString()));
119     }
120 
121     @Test
122     public void testToStringNoTo() {
123         final SimpleSMTPHeader header = new SimpleSMTPHeader("from@here.invalid", null, null);
124         assertNotNull(header);
125         // Note that the DotTerminatedMessageWriter converts LF to CRLF
126         assertEquals("From: from@here.invalid\n\n", checkDate(header.toString()));
127     }
128 }