64
switch (endpoint.attempt_starttls(capabilities.has_capability(Capabilities.STARTTLS))) {
65
case Endpoint.AttemptStarttls.YES:
66
Response response = yield transaction_async(new Request(Command.STARTTLS));
67
if (!response.code.is_starttls_ready()) {
68
throw new SmtpError.STARTTLS_FAILED("STARTTLS failed: %s", response.to_string());
71
// TLS started, lets wrap the connection and shake hands.
72
TlsClientConnection tls_cx = TlsClientConnection.new(cx, socket_cx.get_remote_address());
74
tls_cx.set_validation_flags(TlsCertificateFlags.UNKNOWN_CA);
75
set_data_streams(tls_cx);
76
yield tls_cx.handshake_async(Priority.DEFAULT, cancellable);
78
// Now that we are on an encrypted line we need to say hello again in order to get the
79
// updated capabilities.
80
yield say_hello_async(cancellable);
83
case Endpoint.AttemptStarttls.NO:
87
case Endpoint.AttemptStarttls.HALT:
89
throw new SmtpError.NOT_SUPPORTED("STARTTLS not available for %s", endpoint.to_string());
92
64
Response response = yield transaction_async(authenticator.initiate(), cancellable);
94
66
Logging.debug(Logging.Flag.NETWORK, "[%s] Initiated SMTP %s authentication", to_string(),
107
79
if (data == null || data.length == 0)
108
80
data = DataFormat.CANCEL_AUTHENTICATION.data;
110
Logging.debug(Logging.Flag.NETWORK, "[%s] SMTP AUTH Challenge: %s <%ldb>", to_string(),
111
Geary.String.uint8_to_string(data), data.length);
82
Logging.debug(Logging.Flag.NETWORK, "[%s] SMTP AUTH Challenge recvd", to_string());
113
84
yield Stream.write_all_async(douts, data, 0, -1, Priority.DEFAULT, cancellable);
114
85
douts.put_string(DataFormat.LINE_TERMINATOR);
185
public async Response say_hello_async(Cancellable? cancellable = null) throws Error {
157
* Sends the appropriate HELO/EHLO command and returns the response of the one that worked.
158
* Also saves the server's capabilities in the capabilties property (overwriting any that may
159
* already be present).
161
public async Response say_hello_async(Cancellable? cancellable) throws Error {
188
162
// get local address as FQDN to greet server ... note that this merely returns the DHCP address
189
163
// for machines behind a NAT
190
164
InetAddress local_addr = ((InetSocketAddress) socket_cx.get_local_address()).get_address();
205
179
EhloRequest ehlo = !String.is_empty(fqdn) ? new EhloRequest(fqdn) : new EhloRequest.for_local_address(local_addr);
206
180
Response response = yield transaction_async(ehlo, cancellable);
207
181
if (response.code.is_success_completed()) {
208
// save list of caps returned in EHLO command, skipping first line because it's the
182
// save list of caps returned in EHLO command
210
183
capabilities = new Geary.Smtp.Capabilities();
211
184
capabilities.add_ehlo_response(response);
199
* Sends the appropriate hello command to the server (EHLO / HELO) and establishes whatever
200
* additional connection features are available (STARTTLS, compression). For general-purpose
201
* use, this is the preferred method for establishing a session with a server, as it will do
202
* whatever is necessary to ensure quality-of-service and security.
204
* Note that this does *not* connect to the server; connect_async() should be used before
205
* calling this method.
207
* Returns the Response of the final hello command (there may be more than one).
209
public async Response establish_connection_async(Cancellable? cancellable = null) throws Error {
212
// issue first HELO/EHLO, which will generate a set of capabiltiies
213
Smtp.Response response = yield say_hello_async(cancellable);
215
// STARTTLS, if required
216
switch (endpoint.attempt_starttls(capabilities.has_capability(Capabilities.STARTTLS))) {
217
case Endpoint.AttemptStarttls.YES:
218
Response starttls_response = yield transaction_async(new Request(Command.STARTTLS));
219
if (!starttls_response.code.is_starttls_ready())
220
throw new SmtpError.STARTTLS_FAILED("STARTTLS failed: %s", response.to_string());
222
TlsClientConnection tls_cx = yield endpoint.starttls_handshake_async(cx,
223
socket_cx.get_remote_address(), cancellable);
225
set_data_streams(tls_cx);
227
// Now that we are on an encrypted line we need to say hello again in order to get the
228
// updated capabilities.
229
response = yield say_hello_async(cancellable);
232
case Endpoint.AttemptStarttls.NO:
236
case Endpoint.AttemptStarttls.HALT:
238
throw new SmtpError.NOT_SUPPORTED("STARTTLS not available for %s", endpoint.to_string());
225
244
public async Response quit_async(Cancellable? cancellable = null) throws Error {
226
245
capabilities = null;
227
246
return yield transaction_async(new Request(Command.QUIT), cancellable);