Skip to content

Commit b0c2a4c

Browse files
committed
fix tests, update readme/migration, regen jazzy
1 parent 979acff commit b0c2a4c

36 files changed

Lines changed: 915 additions & 79 deletions

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ macOS & Linux: `Swift 4.0.3` or `Swift 4.1`
2323

2424
## Migration Guide
2525

26-
Version `4.0.0` & `3.0.0` bring breaking changes. See the quick migration guide [here](https://github.com/IBM-Swift/Swift-SMTP/blob/master/migration-guide.md).
26+
Version `5.0.0` brings breaking changes. See the quick migration guide [here](https://github.com/IBM-Swift/Swift-SMTP/blob/master/migration-guide.md).
2727

2828
## Usage
2929

@@ -47,15 +47,15 @@ Additional parameters of `SMTP` struct:
4747
public init(hostname: String,
4848
email: String,
4949
password: String,
50-
port: Int32 = 465,
51-
useTLS: Bool = true,
50+
port: Int32 = 587,
51+
tlsMode: TLSMode = .requireSTARTTLS,
5252
tlsConfiguration: TLSConfiguration? = nil,
5353
authMethods: [AuthMethod] = [],
5454
domainName: String = "localhost",
5555
timeout: UInt = 10)
5656
```
5757

58-
By default, the `SMTP` struct connects on port `465` and tries to connect using TLS. It also uses a `TLSConfiguration` that uses no backing certificates. Configure these to your needs. For more info on `TLSConfiguration`, view the [docs](https://ibm-swift.github.io/Swift-SMTP/Structs/TLSConfiguration.html).
58+
By default, the `SMTP` struct connects on port `587` and sends mail only if a TLS connection can be established. It also uses a `TLSConfiguration` that uses no backing certificates. View the [docs](https://ibm-swift.github.io/Swift-SMTP/) for more configuration options.
5959

6060
### Send email
6161

Sources/SwiftSMTP/SMTP.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@ public struct SMTP {
2828
private let domainName: String
2929
private let timeout: UInt
3030

31-
/// TLSMode enum for what form of connection security to enforce
31+
/// TLSMode enum for what form of connection security to enforce.
3232
public enum TLSMode {
3333
/// Upgrades the connection to TLS if STARTLS command is received, else sends mail without security.
3434
case normal
3535

3636
/// Send mail over plaintext and ignore STARTTLS commands and TLS options. Could throw an error if server requires TLS.
3737
case ignoreTLS
3838

39-
/// Only send mail after an initial successful TLS connection. Connection will fail if a TLS connection cannot be established.
39+
/// Only send mail after an initial successful TLS connection. Connection will fail if a TLS connection cannot be established. The default port, 587, will likely need to be adjusted depending on your server.
4040
case requireTLS
4141

42-
/// Expect a STARTTLS command from the server and require the connection is upgraded to TLS. Will throw if the server does not issue a STARTTLS command
42+
/// Expect a STARTTLS command from the server and require the connection is upgraded to TLS. Will throw if the server does not issue a STARTTLS command.
4343
case requireSTARTTLS
4444
}
4545

@@ -50,7 +50,7 @@ public struct SMTP {
5050
/// - email: Username to log in to server.
5151
/// - password: Password to log in to server, or access token if using XOAUTH2 authorization method.
5252
/// - port: Port to connect to the server on. Defaults to `465`.
53-
/// - tlsMode: TLSMode `enum` indicating what form of connection security to use
53+
/// - tlsMode: TLSMode `enum` indicating what form of connection security to use.
5454
/// - tlsConfiguration: `TLSConfiguration` used to connect with TLS. If nil, a configuration with no backing
5555
/// certificates is used. See `TLSConfiguration` for other configuration options.
5656
/// - authMethods: `AuthMethod`s to use to log in to the server. If blank, tries all supported methods.

Sources/SwiftSMTP/SMTPError.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ public enum SMTPError: Error, CustomStringConvertible {
3030
/// File not found at path while trying to send file `Attachment`.
3131
case fileNotFound(path: String)
3232

33-
/// The preferred `AuthMethod`s could not be found. Connecting with `SSL` may be required.
34-
case noSupportedAuthMethods(hostname: String)
33+
/// The preferred `AuthMethod`s could not be found, or your server is sending back a STARTTLS command and requires a connection upgrade.
34+
case noAuthMethodsOrRequiresTLS(hostname: String)
3535

3636
// Sender
3737
/// Mail has no recipients.
@@ -51,7 +51,7 @@ public enum SMTPError: Error, CustomStringConvertible {
5151
/// Invalid email provided for `User`.
5252
case invalidEmail(email: String)
5353

54-
/// STARTTLS was required but the server did not request it
54+
/// STARTTLS was required but the server did not request it.
5555
case requiredSTARTTLS
5656

5757
/// Description of the `SMTPError`.
@@ -60,7 +60,7 @@ public enum SMTPError: Error, CustomStringConvertible {
6060
case .base64DecodeFail(let s): return "Error decoding string: \(s)."
6161
case .md5HashChallengeFail: return "Hashing server challenge with MD5 algorithm failed."
6262
case .fileNotFound(let p): return "File not found at path while trying to send file `Attachment`: \(p)."
63-
case .noSupportedAuthMethods(let hostname): return "The preferred authorization methods could not be found on \(hostname). Connecting with SSL may be required."
63+
case .noAuthMethodsOrRequiresTLS(let hostname): return "The preferred authorization methods could not be found on \(hostname), or your server is sending back a STARTTLS command and requires a connection upgrade."
6464
case .noRecipients: return "An email requires at least one recipient."
6565
case .createEmailRegexFailed: return "Failed to create RegularExpression that can check if an email is valid."
6666
case .badResponse(let command, let response): return "Bad response received for command. command: (\(command)), response: \(response)"

Sources/SwiftSMTP/SMTPSocket.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ struct SMTPSocket {
4141
try socket.connect(to: hostname, port: port, timeout: timeout * 1000)
4242
try parseResponses(readFromSocket(), command: .connect)
4343
var serverOptions = try getServerOptions(domainName: domainName)
44-
if (tlsMode == .requireSTARTTLS || tlsMode == .normal) {
45-
if (try doStarttls(serverOptions: serverOptions, tlsConfiguration:tlsConfiguration)) {
44+
if tlsMode == .requireSTARTTLS || tlsMode == .normal {
45+
if try doStarttls(serverOptions: serverOptions, tlsConfiguration: tlsConfiguration) {
4646
serverOptions = try getServerOptions(domainName: domainName)
47-
} else if (tlsMode == .requireSTARTTLS) {
47+
} else if tlsMode == .requireSTARTTLS {
4848
throw SMTPError.requiredSTARTTLS
4949
}
5050
}
@@ -159,20 +159,22 @@ private extension SMTPSocket {
159159
}
160160
}
161161
}
162-
throw SMTPError.noSupportedAuthMethods(hostname: hostname)
162+
throw SMTPError.noAuthMethodsOrRequiresTLS(hostname: hostname)
163163
}
164+
164165
func doStarttls(serverOptions: [Response], tlsConfiguration: TLSConfiguration?) throws -> Bool {
165166
for option in serverOptions {
166167
if option.message == "STARTTLS" {
167-
try starttls(tlsConfiguration:tlsConfiguration)
168+
try starttls(tlsConfiguration: tlsConfiguration)
168169
return true
169170
}
170171
}
171172
return false
172173
}
174+
173175
func starttls(tlsConfiguration: TLSConfiguration?) throws {
174176
try send(.starttls)
175-
//Upgrade the socket to SSL/TLS
177+
// Upgrade the socket to SSL/TLS
176178
if let tlsConfiguration = tlsConfiguration {
177179
socket.delegate = try tlsConfiguration.makeSSLService()
178180
} else {

Tests/SwiftSMTPTests/Constant.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ let testDuration: Double = 15
2828
let hostname = "smtp.gmail.com"
2929
let myEmail: String? = nil
3030
let myPassword: String? = nil
31-
let port: Int32 = 465
32-
let useTLS = true
31+
let port: Int32 = 587
3332
let authMethods: [String: AuthMethod] = [
3433
AuthMethod.cramMD5.rawValue: .cramMD5,
3534
AuthMethod.login.rawValue: .login,
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* Copyright IBM Corporation 2018
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
**/
16+
17+
import XCTest
18+
@testable import SwiftSMTP
19+
20+
class TestTLSMode: XCTestCase {
21+
static var allTests = [
22+
("testNormal", testNormal),
23+
("testIgnoreTLS", testIgnoreTLS),
24+
("testRequireTLS", testRequireTLS),
25+
("testRequireSTARTTLS", testRequireSTARTTLS)
26+
]
27+
28+
func testNormal() {
29+
let expectation = self.expectation(description: #function)
30+
defer { waitForExpectations(timeout: testDuration) }
31+
32+
do {
33+
_ = try SMTPSocket(
34+
hostname: hostname,
35+
email: email,
36+
password: password,
37+
port: port,
38+
tlsMode: .normal,
39+
tlsConfiguration: nil,
40+
authMethods: authMethods,
41+
domainName: domainName,
42+
timeout: timeout
43+
)
44+
expectation.fulfill()
45+
} catch {
46+
XCTFail(String(describing: error))
47+
expectation.fulfill()
48+
}
49+
}
50+
51+
func testIgnoreTLS() {
52+
let expectation = self.expectation(description: #function)
53+
defer { waitForExpectations(timeout: testDuration) }
54+
55+
do {
56+
_ = try SMTPSocket(
57+
hostname: hostname,
58+
email: email,
59+
password: password,
60+
port: port,
61+
tlsMode: .ignoreTLS,
62+
tlsConfiguration: nil,
63+
authMethods: authMethods,
64+
domainName: domainName,
65+
timeout: timeout
66+
)
67+
XCTFail()
68+
expectation.fulfill()
69+
} catch {
70+
if case SMTPError.noAuthMethodsOrRequiresTLS = error {
71+
expectation.fulfill()
72+
} else {
73+
XCTFail(String(describing: error))
74+
expectation.fulfill()
75+
}
76+
}
77+
}
78+
79+
func testRequireTLS() {
80+
let expectation = self.expectation(description: #function)
81+
defer { waitForExpectations(timeout: testDuration) }
82+
83+
do {
84+
_ = try SMTPSocket(
85+
hostname: hostname,
86+
email: email,
87+
password: password,
88+
port: 465,
89+
tlsMode: .requireTLS,
90+
tlsConfiguration: nil,
91+
authMethods: authMethods,
92+
domainName: domainName,
93+
timeout: timeout
94+
)
95+
expectation.fulfill()
96+
} catch {
97+
XCTFail(String(describing: error))
98+
expectation.fulfill()
99+
}
100+
}
101+
102+
func testRequireSTARTTLS() {
103+
let expectation = self.expectation(description: #function)
104+
defer { waitForExpectations(timeout: testDuration) }
105+
106+
do {
107+
_ = try SMTPSocket(
108+
hostname: hostname,
109+
email: email,
110+
password: password,
111+
port: port,
112+
tlsMode: .requireSTARTTLS,
113+
tlsConfiguration: nil,
114+
authMethods: authMethods,
115+
domainName: domainName,
116+
timeout: timeout
117+
)
118+
expectation.fulfill()
119+
} catch {
120+
XCTFail(String(describing: error))
121+
expectation.fulfill()
122+
}
123+
}
124+
}

docs/Enums.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@
7575
<li class="nav-group-task">
7676
<a class="nav-group-task-link" href="Structs/SMTP.html">SMTP</a>
7777
</li>
78+
<li class="nav-group-task">
79+
<a class="nav-group-task-link" href="Structs/SMTP/TLSMode.html">– TLSMode</a>
80+
</li>
7881
<li class="nav-group-task">
7982
<a class="nav-group-task-link" href="Structs/TLSConfiguration.html">TLSConfiguration</a>
8083
</li>
@@ -175,7 +178,7 @@ <h4>Declaration</h4>
175178
</article>
176179
</div>
177180
<section class="footer">
178-
<p>&copy; 2018 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2018-04-30)</p>
181+
<p>&copy; 2018 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2018-06-26)</p>
179182
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.9.0</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
180183
</section>
181184
</body>

docs/Enums/AuthMethod.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@
7676
<li class="nav-group-task">
7777
<a class="nav-group-task-link" href="../Structs/SMTP.html">SMTP</a>
7878
</li>
79+
<li class="nav-group-task">
80+
<a class="nav-group-task-link" href="../Structs/SMTP/TLSMode.html">– TLSMode</a>
81+
</li>
7982
<li class="nav-group-task">
8083
<a class="nav-group-task-link" href="../Structs/TLSConfiguration.html">TLSConfiguration</a>
8184
</li>
@@ -242,7 +245,7 @@ <h4>Declaration</h4>
242245
</article>
243246
</div>
244247
<section class="footer">
245-
<p>&copy; 2018 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2018-04-30)</p>
248+
<p>&copy; 2018 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2018-06-26)</p>
246249
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.9.0</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
247250
</section>
248251
</body>

docs/Enums/SMTPError.html

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@
7676
<li class="nav-group-task">
7777
<a class="nav-group-task-link" href="../Structs/SMTP.html">SMTP</a>
7878
</li>
79+
<li class="nav-group-task">
80+
<a class="nav-group-task-link" href="../Structs/SMTP/TLSMode.html">– TLSMode</a>
81+
</li>
7982
<li class="nav-group-task">
8083
<a class="nav-group-task-link" href="../Structs/TLSConfiguration.html">TLSConfiguration</a>
8184
</li>
@@ -210,24 +213,24 @@ <h4>Declaration</h4>
210213
<li class="item">
211214
<div>
212215
<code>
213-
<a name="/s:9SwiftSMTP9SMTPErrorO22noSupportedAuthMethodsACSS8hostname_tcACmF"></a>
214-
<a name="//apple_ref/swift/Element/noSupportedAuthMethods" class="dashAnchor"></a>
215-
<a class="token" href="#/s:9SwiftSMTP9SMTPErrorO22noSupportedAuthMethodsACSS8hostname_tcACmF">noSupportedAuthMethods</a>
216+
<a name="/s:9SwiftSMTP9SMTPErrorO26noAuthMethodsOrRequiresTLSACSS8hostname_tcACmF"></a>
217+
<a name="//apple_ref/swift/Element/noAuthMethodsOrRequiresTLS" class="dashAnchor"></a>
218+
<a class="token" href="#/s:9SwiftSMTP9SMTPErrorO26noAuthMethodsOrRequiresTLSACSS8hostname_tcACmF">noAuthMethodsOrRequiresTLS</a>
216219
</code>
217220
</div>
218221
<div class="height-container">
219222
<div class="pointer-container"></div>
220223
<section class="section">
221224
<div class="pointer"></div>
222225
<div class="abstract">
223-
<p>The preferred <code><a href="../Enums/AuthMethod.html">AuthMethod</a></code>s could not be found. Connecting with <code>SSL</code> may be required.</p>
226+
<p>The preferred <code><a href="../Enums/AuthMethod.html">AuthMethod</a></code>s could not be found, or your server is sending back a STARTTLS command and requires a connection upgrade.</p>
224227

225228
</div>
226229
<div class="declaration">
227230
<h4>Declaration</h4>
228231
<div class="language">
229232
<p class="aside-title">Swift</p>
230-
<pre class="highlight"><code><span class="k">case</span> <span class="nf">noSupportedAuthMethods</span><span class="p">(</span><span class="nv">hostname</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span></code></pre>
233+
<pre class="highlight"><code><span class="k">case</span> <span class="nf">noAuthMethodsOrRequiresTLS</span><span class="p">(</span><span class="nv">hostname</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span></code></pre>
231234

232235
</div>
233236
</div>
@@ -391,6 +394,37 @@ <h4>Declaration</h4>
391394
</li>
392395
</ul>
393396
</div>
397+
<div class="task-group">
398+
<ul class="item-container">
399+
<li class="item">
400+
<div>
401+
<code>
402+
<a name="/s:9SwiftSMTP9SMTPErrorO16requiredSTARTTLSA2CmF"></a>
403+
<a name="//apple_ref/swift/Element/requiredSTARTTLS" class="dashAnchor"></a>
404+
<a class="token" href="#/s:9SwiftSMTP9SMTPErrorO16requiredSTARTTLSA2CmF">requiredSTARTTLS</a>
405+
</code>
406+
</div>
407+
<div class="height-container">
408+
<div class="pointer-container"></div>
409+
<section class="section">
410+
<div class="pointer"></div>
411+
<div class="abstract">
412+
<p>STARTTLS was required but the server did not request it.</p>
413+
414+
</div>
415+
<div class="declaration">
416+
<h4>Declaration</h4>
417+
<div class="language">
418+
<p class="aside-title">Swift</p>
419+
<pre class="highlight"><code><span class="k">case</span> <span class="n">requiredSTARTTLS</span></code></pre>
420+
421+
</div>
422+
</div>
423+
</section>
424+
</div>
425+
</li>
426+
</ul>
427+
</div>
394428
<div class="task-group">
395429
<ul class="item-container">
396430
<li class="item">
@@ -428,7 +462,7 @@ <h4>Declaration</h4>
428462
</article>
429463
</div>
430464
<section class="footer">
431-
<p>&copy; 2018 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2018-04-30)</p>
465+
<p>&copy; 2018 <a class="link" href="" target="_blank" rel="external">IBM</a>. All rights reserved. (Last updated: 2018-06-26)</p>
432466
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.9.0</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
433467
</section>
434468
</body>

0 commit comments

Comments
 (0)