Closes #4780. This adds support for STARTTLS with SMTP as well as replaces the previous uses of "TLS" with "SSL" to prevent confusion related to the two similar protocols.

Also it adds debug support to geary-mailer.
This commit is contained in:
Nate Lillich 2012-05-24 12:14:05 -07:00
parent ebdb58f874
commit 2f2dca09b1
16 changed files with 162 additions and 108 deletions

View file

@ -131,7 +131,7 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
Geary.Logging.log_to(stdout);
return 0;
}
}
public override int startup() {
exec_dir = (File.new_for_path(Environment.find_program_in_path(args[0]))).get_parent();
@ -227,11 +227,11 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
account_info.imap_server_host = login.imap_host;
account_info.imap_server_port = login.imap_port;
account_info.imap_server_tls = login.imap_tls;
account_info.imap_server_ssl = login.imap_ssl;
account_info.imap_server_pipeline = (login.provider != Geary.ServiceProvider.OTHER);
account_info.smtp_server_host = login.smtp_host;
account_info.smtp_server_port = login.smtp_port;
account_info.smtp_server_tls = login.smtp_tls;
account_info.smtp_server_ssl = login.smtp_ssl;
} else {
exit(1);
return null;

View file

@ -15,10 +15,10 @@ public class LoginDialog {
private Gtk.Alignment other_info;
private Gtk.Entry entry_imap_host;
private Gtk.Entry entry_imap_port;
private Gtk.CheckButton check_imap_tls;
private Gtk.CheckButton check_imap_ssl;
private Gtk.Entry entry_smtp_host;
private Gtk.Entry entry_smtp_port;
private Gtk.CheckButton check_smtp_tls;
private Gtk.CheckButton check_smtp_ssl;
private Gtk.ResponseType response;
private Gtk.Button ok_button;
@ -34,12 +34,12 @@ public class LoginDialog {
public string imap_host { get; private set; default = ""; }
public uint16 imap_port { get; private set;
default = Geary.Imap.ClientConnection.DEFAULT_PORT_TLS; }
public bool imap_tls { get; private set; default = true; }
default = Geary.Imap.ClientConnection.DEFAULT_PORT_SSL; }
public bool imap_ssl { get; private set; default = true; }
public string smtp_host { get; private set; default = ""; }
public uint16 smtp_port { get; private set;
default = Geary.Smtp.ClientConnection.SECURE_SMTP_PORT; }
public bool smtp_tls { get; private set; default = true; }
default = Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL; }
public bool smtp_ssl { get; private set; default = true; }
public LoginDialog(string default_real_name = "", string default_username = "", string default_password = "",
Geary.AccountInformation? default_account_info = null) {
@ -57,10 +57,10 @@ public class LoginDialog {
other_info = builder.get_object("other_info") as Gtk.Alignment;
entry_imap_host = builder.get_object("imap host") as Gtk.Entry;
entry_imap_port = builder.get_object("imap port") as Gtk.Entry;
check_imap_tls = builder.get_object("imap tls") as Gtk.CheckButton;
check_imap_ssl = builder.get_object("imap ssl") as Gtk.CheckButton;
entry_smtp_host = builder.get_object("smtp host") as Gtk.Entry;
entry_smtp_port = builder.get_object("smtp port") as Gtk.Entry;
check_smtp_tls = builder.get_object("smtp tls") as Gtk.CheckButton;
check_smtp_ssl = builder.get_object("smtp ssl") as Gtk.CheckButton;
combo_service.changed.connect(on_service_changed);
@ -94,8 +94,8 @@ public class LoginDialog {
entry_smtp_host.changed.connect(on_changed);
entry_smtp_port.changed.connect(on_changed);
check_imap_tls.toggled.connect(on_check_imap_tls_toggled);
check_smtp_tls.toggled.connect(on_check_smtp_tls_toggled);
check_imap_ssl.toggled.connect(on_check_imap_ssl_toggled);
check_smtp_ssl.toggled.connect(on_check_smtp_ssl_toggled);
entry_imap_port.insert_text.connect(on_port_insert_text);
entry_smtp_port.insert_text.connect(on_port_insert_text);
@ -122,10 +122,10 @@ public class LoginDialog {
provider = get_service_provider();
imap_host = entry_imap_host.text.strip();
imap_port = (uint16) int.parse(entry_imap_port.text.strip());
imap_tls = check_imap_tls.active;
imap_ssl = check_imap_ssl.active;
smtp_host = entry_smtp_host.text.strip();
smtp_port = (uint16) int.parse(entry_smtp_port.text.strip());
smtp_tls = check_smtp_tls.active;
smtp_ssl = check_smtp_ssl.active;
dialog.destroy();
}
@ -160,20 +160,20 @@ public class LoginDialog {
}
}
private void on_check_imap_tls_toggled() {
private void on_check_imap_ssl_toggled() {
if (edited_imap_port)
return;
entry_imap_port.text = (check_imap_tls.active ? Geary.Imap.ClientConnection.DEFAULT_PORT_TLS :
entry_imap_port.text = (check_imap_ssl.active ? Geary.Imap.ClientConnection.DEFAULT_PORT_SSL :
Geary.Imap.ClientConnection.DEFAULT_PORT).to_string();
edited_imap_port = false;
}
private void on_check_smtp_tls_toggled() {
private void on_check_smtp_ssl_toggled() {
if (edited_smtp_port)
return;
entry_smtp_port.text = (check_smtp_tls.active ? Geary.Smtp.ClientConnection.SECURE_SMTP_PORT :
entry_smtp_port.text = (check_smtp_ssl.active ? Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL :
Geary.Smtp.ClientConnection.DEFAULT_PORT).to_string();
edited_smtp_port = false;
}

View file

@ -279,8 +279,8 @@ class ImapConsole : Gtk.Window {
check_args(cmd, args, 1, "hostname[:port]");
cx = new Geary.Imap.ClientConnection(
new Geary.Endpoint(args[0], Geary.Imap.ClientConnection.DEFAULT_PORT_TLS,
Geary.Endpoint.Flags.TLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
new Geary.Endpoint(args[0], Geary.Imap.ClientConnection.DEFAULT_PORT_SSL,
Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Geary.Imap.ClientConnection.DEFAULT_TIMEOUT_SEC));
cx.sent_command.connect(on_sent_command);

View file

@ -10,24 +10,24 @@ public class Geary.AccountInformation : Object {
private const string SERVICE_PROVIDER_KEY = "service_provider";
private const string IMAP_HOST = "imap_host";
private const string IMAP_PORT = "imap_port";
private const string IMAP_TLS = "imap_tls";
private const string IMAP_SSL = "imap_ssl";
private const string IMAP_PIPELINE = "imap_pipeline";
private const string SMTP_HOST = "smtp_host";
private const string SMTP_PORT = "smtp_port";
private const string SMTP_TLS = "smtp_tls";
private const string SMTP_SSL = "smtp_ssl";
internal File? file = null;
public string real_name { get; set; }
public Geary.ServiceProvider service_provider { get; set; }
public string imap_server_host { get; set; default = ""; }
public uint16 imap_server_port { get; set; default = Imap.ClientConnection.DEFAULT_PORT_TLS; }
public bool imap_server_tls { get; set; default = true; }
public uint16 imap_server_port { get; set; default = Imap.ClientConnection.DEFAULT_PORT_SSL; }
public bool imap_server_ssl { get; set; default = true; }
public bool imap_server_pipeline { get; set; default = true; }
public string smtp_server_host { get; set; default = ""; }
public uint16 smtp_server_port { get; set; default = Smtp.ClientConnection.SECURE_SMTP_PORT; }
public bool smtp_server_tls { get; set; default = true; }
public uint16 smtp_server_port { get; set; default = Smtp.ClientConnection.DEFAULT_PORT_SSL; }
public bool smtp_server_ssl { get; set; default = true; }
public AccountInformation() {
}
@ -46,14 +46,14 @@ public class Geary.AccountInformation : Object {
imap_server_host = get_string_value(key_file, GROUP, IMAP_HOST);
imap_server_port = get_uint16_value(key_file, GROUP, IMAP_PORT,
Imap.ClientConnection.DEFAULT_PORT_TLS);
imap_server_tls = get_bool_value(key_file, GROUP, IMAP_TLS, true);
Imap.ClientConnection.DEFAULT_PORT_SSL);
imap_server_ssl = get_bool_value(key_file, GROUP, IMAP_SSL, true);
imap_server_pipeline = get_bool_value(key_file, GROUP, IMAP_PIPELINE, true);
smtp_server_host = get_string_value(key_file, GROUP, SMTP_HOST);
smtp_server_port = get_uint16_value(key_file, GROUP, SMTP_PORT,
Geary.Smtp.ClientConnection.SECURE_SMTP_PORT);
smtp_server_tls = get_bool_value(key_file, GROUP, SMTP_TLS, true);
Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL);
smtp_server_ssl = get_bool_value(key_file, GROUP, SMTP_SSL, true);
}
}
@ -99,12 +99,12 @@ public class Geary.AccountInformation : Object {
key_file.set_value(GROUP, IMAP_HOST, imap_server_host);
key_file.set_integer(GROUP, IMAP_PORT, imap_server_port);
key_file.set_boolean(GROUP, IMAP_TLS, imap_server_tls);
key_file.set_boolean(GROUP, IMAP_SSL, imap_server_ssl);
key_file.set_boolean(GROUP, IMAP_PIPELINE, imap_server_pipeline);
key_file.set_value(GROUP, SMTP_HOST, smtp_server_host);
key_file.set_integer(GROUP, SMTP_PORT, smtp_server_port);
key_file.set_boolean(GROUP, SMTP_TLS, smtp_server_tls);
key_file.set_boolean(GROUP, SMTP_SSL, smtp_server_ssl);
string data = key_file.to_data();
string new_etag;

View file

@ -8,7 +8,8 @@ public class Geary.Endpoint : Object {
[Flags]
public enum Flags {
NONE = 0,
TLS,
SSL,
STARTTLS,
GRACEFUL_DISCONNECT;
public inline bool is_all_set(Flags flags) {
@ -37,30 +38,30 @@ public class Geary.Endpoint : Object {
public SocketClient get_socket_client() {
if (socket_client != null)
return socket_client;
socket_client = new SocketClient();
if (flags.is_all_set(Flags.TLS)) {
if (flags.is_all_set(Flags.SSL)) {
socket_client.set_tls(true);
socket_client.set_tls_validation_flags(TlsCertificateFlags.UNKNOWN_CA);
}
socket_client.set_timeout(timeout_sec);
return socket_client;
}
public async SocketConnection connect_async(Cancellable? cancellable = null) throws Error {
SocketConnection cx = yield get_socket_client().connect_to_host_async(host_specifier, default_port,
cancellable);
TcpConnection? tcp = cx as TcpConnection;
if (tcp != null)
tcp.set_graceful_disconnect(flags.is_all_set(Flags.GRACEFUL_DISCONNECT));
return cx;
}
public string to_string() {
return "%s/default:%u".printf(host_specifier, default_port);
}

View file

@ -50,11 +50,11 @@ public class Geary.Engine {
account_info), new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
case ServiceProvider.OTHER:
Endpoint.Flags imap_flags = account_info.imap_server_tls ? Endpoint.Flags.TLS
Endpoint.Flags imap_flags = account_info.imap_server_ssl ? Endpoint.Flags.SSL
: Endpoint.Flags.NONE;
imap_flags |= Endpoint.Flags.GRACEFUL_DISCONNECT;
Endpoint.Flags smtp_flags = account_info.smtp_server_tls ? Endpoint.Flags.TLS
Endpoint.Flags smtp_flags = account_info.smtp_server_ssl ? Endpoint.Flags.SSL
: Endpoint.Flags.NONE;
smtp_flags |= Geary.Endpoint.Flags.GRACEFUL_DISCONNECT;

View file

@ -6,7 +6,7 @@
public class Geary.Imap.ClientConnection {
public const uint16 DEFAULT_PORT = 143;
public const uint16 DEFAULT_PORT_TLS = 993;
public const uint16 DEFAULT_PORT_SSL = 993;
// TODO: This is set very high to allow for IDLE connections to remain connected even when
// there is no traffic on them. The side-effect is that if the physical connection is dropped,

View file

@ -12,8 +12,8 @@ private class Geary.GmailAccount : Geary.GenericImapAccount {
if (_imap_endpoint == null) {
_imap_endpoint = new Geary.Endpoint(
"imap.gmail.com",
Imap.ClientConnection.DEFAULT_PORT_TLS,
Geary.Endpoint.Flags.TLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Imap.ClientConnection.DEFAULT_PORT_SSL,
Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Imap.ClientConnection.DEFAULT_TIMEOUT_SEC);
}
@ -25,8 +25,8 @@ private class Geary.GmailAccount : Geary.GenericImapAccount {
if (_smtp_endpoint == null) {
_smtp_endpoint = new Geary.Endpoint(
"smtp.gmail.com",
Smtp.ClientConnection.SECURE_SMTP_PORT,
Geary.Endpoint.Flags.TLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Smtp.ClientConnection.DEFAULT_PORT_SSL,
Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
}

View file

@ -10,8 +10,8 @@ private class Geary.YahooAccount : Geary.GenericImapAccount {
if (_imap_endpoint == null) {
_imap_endpoint = new Geary.Endpoint(
"imap.mail.yahoo.com",
Imap.ClientConnection.DEFAULT_PORT_TLS,
Geary.Endpoint.Flags.TLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Imap.ClientConnection.DEFAULT_PORT_SSL,
Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Imap.ClientConnection.DEFAULT_TIMEOUT_SEC);
}
@ -23,8 +23,8 @@ private class Geary.YahooAccount : Geary.GenericImapAccount {
if (_smtp_endpoint == null) {
_smtp_endpoint = new Geary.Endpoint(
"smtp.mail.yahoo.com",
Smtp.ClientConnection.SECURE_SMTP_PORT,
Geary.Endpoint.Flags.TLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Smtp.ClientConnection.DEFAULT_PORT_SSL,
Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
}

View file

@ -6,15 +6,17 @@
public class Geary.Smtp.ClientConnection {
public const uint16 DEFAULT_PORT = 25;
public const uint16 SUBMISSION_PORT = 587;
public const uint16 SECURE_SMTP_PORT = 465;
public const uint16 DEFAULT_PORT_SSL = 465;
public const uint16 DEFAULT_PORT_STARTTLS = 587;
public const uint DEFAULT_TIMEOUT_SEC = 60;
private Geary.Endpoint endpoint;
private SocketConnection? cx = null;
private IOStream? cx = null;
private SocketConnection? socket_cx = null;
private DataInputStream? dins = null;
private DataOutputStream douts = null;
private Gee.List<string>? capabilities = null;
public ClientConnection(Geary.Endpoint endpoint) {
this.endpoint = endpoint;
@ -31,11 +33,8 @@ public class Geary.Smtp.ClientConnection {
return null;
}
cx = yield endpoint.connect_async(cancellable);
dins = new DataInputStream(cx.input_stream);
dins.set_newline_type(DataFormat.LINE_TERMINATOR_TYPE);
douts = new DataOutputStream(cx.output_stream);
cx = socket_cx = yield endpoint.connect_async(cancellable);
set_data_streams(cx);
// read and deserialize the greeting
return Greeting.deserialize(yield read_line_async(cancellable));
@ -50,16 +49,35 @@ public class Geary.Smtp.ClientConnection {
return true;
}
/**
* Returns the final Response of the challenge-response.
*/
public async Response authenticate_async(Authenticator authenticator, Cancellable? cancellable = null)
throws Error {
check_connected();
Response response = yield transaction_async(authenticator.initiate(), cancellable);
Response response;
if (endpoint.flags.is_all_set(Endpoint.Flags.STARTTLS)) {
response = yield transaction_async(new Request(Command.STARTTLS));
if (!response.code.is_starttls_ready()) {
throw new SmtpError.STARTTLS_FAILED("STARTTLS failed: %s", response.to_string());
}
// TLS started, lets wrap the connection and shake hands.
TlsClientConnection tls_cx = TlsClientConnection.new(cx, socket_cx.get_remote_address());
cx = tls_cx;
tls_cx.set_validation_flags(TlsCertificateFlags.UNKNOWN_CA);
set_data_streams(tls_cx);
yield tls_cx.handshake_async(Priority.DEFAULT, cancellable);
// Now that we are on an encrypted line we need to say hello again in order to get the
// updated capabilities.
yield say_hello_async(cancellable);
}
response = yield transaction_async(authenticator.initiate(), cancellable);
// Possible for initiate() Request to:
// (a) immediately generate success (due to valid authentication being passed in Request);
// (b) immediately fails;
@ -72,17 +90,17 @@ public class Geary.Smtp.ClientConnection {
uint8[]? data = authenticator.challenge(step++, response);
if (data == null || data.length == 0)
data = DataFormat.CANCEL_AUTHENTICATION.data;
yield Stream.write_all_async(douts, data, 0, -1, Priority.DEFAULT, cancellable);
douts.put_string(DataFormat.LINE_TERMINATOR);
yield douts.flush_async(Priority.DEFAULT, cancellable);
response = yield recv_response_async(cancellable);
}
return response;
}
/**
* Sends a block of data (mail message) by first issuing the DATA command and transmitting
* the block if the appropriate response is sent. The data block should *not* have the SMTP
@ -132,11 +150,35 @@ public class Geary.Smtp.ClientConnection {
return new Response(lines);
}
public async Response say_hello_async(Cancellable? cancellable = null) throws Error {
// try EHLO first, then fall back on HELO
Response response = yield transaction_async(new Request(Command.EHLO), cancellable);
if (response.code.is_success_completed()) {
// save list of caps returned in EHLO command, skipping first line because it's the
// EHLO response
capabilities = new Gee.ArrayList<string>();
for (int ctr = 1; ctr < response.lines.size; ctr++) {
if (!String.is_empty(response.lines[ctr].explanation))
capabilities.add(response.lines[ctr].explanation);
}
} else {
response = yield transaction_async(new Request(Command.HELO), cancellable);
if (!response.code.is_success_completed())
throw new SmtpError.SERVER_ERROR("Refused service: %s", response.to_string());
}
return response;
}
public async Response quit_async(Cancellable? cancellable = null) throws Error {
capabilities = null;
return yield transaction_async(new Request(Command.QUIT), cancellable);
}
public async Response transaction_async(Request request, Cancellable? cancellable = null)
throws Error {
yield send_request_async(request, cancellable);
return yield recv_response_async(cancellable);
}
@ -158,5 +200,13 @@ public class Geary.Smtp.ClientConnection {
public string to_string() {
return endpoint.to_string();
}
private void set_data_streams(IOStream stream) {
dins = new DataInputStream(stream.input_stream);
dins.set_newline_type(DataFormat.LINE_TERMINATOR_TYPE);
dins.set_close_base_stream(false);
douts = new DataOutputStream(stream.output_stream);
douts.set_close_base_stream(false);
}
}

View file

@ -6,7 +6,6 @@
public class Geary.Smtp.ClientSession {
private ClientConnection cx;
private Gee.List<string>? capabilities = null;
private bool rset_required = false;
public virtual signal void connected(Greeting greeting) {
@ -37,35 +36,21 @@ public class Geary.Smtp.ClientSession {
public async Greeting? login_async(Credentials? creds, Cancellable? cancellable = null) throws Error {
if (cx.is_connected())
throw new SmtpError.ALREADY_CONNECTED("Connection to %s already exists", to_string());
// Greet the SMTP server.
Greeting? greeting = yield cx.connect_async(cancellable);
if (greeting == null)
throw new SmtpError.ALREADY_CONNECTED("Connection to %s already exists", to_string());
// try EHLO first, then fall back on HELO
Response response = yield cx.transaction_async(new Request(Command.EHLO), cancellable);
if (response.code.is_success_completed()) {
// save list of caps returned in EHLO command, skipping first line because it's the
// EHLO response
capabilities = new Gee.ArrayList<string>();
for (int ctr = 1; ctr < response.lines.size; ctr++) {
if (!String.is_empty(response.lines[ctr].explanation))
capabilities.add(response.lines[ctr].explanation);
}
} else {
response = yield cx.transaction_async(new Request(Command.HELO), cancellable);
if (!response.code.is_success_completed())
throw new SmtpError.SERVER_ERROR("Refused service: %s", response.to_string());
}
yield cx.say_hello_async(cancellable);
notify_connected(greeting);
// authenticate if credentials supplied (in almost every case they should be)
// TODO: Select an authentication method based on AUTH capabilities line, falling back on
// LOGIN or PLAIN if none match or are present
if (creds != null) {
Authenticator authenticator = new LoginAuthenticator(creds);
response = yield cx.authenticate_async(authenticator, cancellable);
Response response = yield cx.authenticate_async(authenticator, cancellable);
if (!response.code.is_success_completed())
throw new SmtpError.AUTHENTICATION_FAILED("Unable to authenticate with %s", to_string());
@ -74,11 +59,11 @@ public class Geary.Smtp.ClientSession {
return greeting;
}
public async Response? logout_async(Cancellable? cancellable = null) throws Error {
Response? response = null;
try {
response = yield cx.transaction_async(new Request(Command.QUIT), cancellable);
response = yield cx.quit_async(cancellable);
} catch (Error err) {
// catch because although error occurred, still attempt to close the connection
message("Unable to QUIT: %s", err.message);
@ -93,8 +78,7 @@ public class Geary.Smtp.ClientSession {
}
rset_required = false;
capabilities = null;
return response;
}

View file

@ -14,7 +14,8 @@ public enum Geary.Smtp.Command {
AUTH,
MAIL,
RCPT,
DATA;
DATA,
STARTTLS;
public string serialize() {
switch (this) {
@ -47,7 +48,10 @@ public enum Geary.Smtp.Command {
case DATA:
return "data";
case STARTTLS:
return "starttls";
default:
assert_not_reached();
}
@ -84,7 +88,10 @@ public enum Geary.Smtp.Command {
case "data":
return DATA;
case "starttls":
return STARTTLS;
default:
throw new SmtpError.PARSE_ERROR("Unknown command \"%s\"", str);
}

View file

@ -6,6 +6,7 @@
public errordomain Geary.SmtpError {
PARSE_ERROR,
STARTTLS_FAILED,
AUTHENTICATION_FAILED,
SERVER_ERROR,
ALREADY_CONNECTED,

View file

@ -11,6 +11,7 @@ public class Geary.Smtp.ResponseCode {
public const int MAX = 599;
public const string START_DATA_CODE = "354";
public const string STARTTLS_READY_CODE = "220";
public enum Status {
POSITIVE_PRELIMINARY = 1,
@ -95,11 +96,15 @@ public class Geary.Smtp.ResponseCode {
return false;
}
}
public bool is_start_data() {
return str == START_DATA_CODE;
}
public bool is_starttls_ready() {
return str == STARTTLS_READY_CODE;
}
public string serialize() {
return str;
}

View file

@ -47,6 +47,7 @@ void on_main_completed(Object? object, AsyncResult result) {
string arg_hostname;
int arg_port = 25;
bool arg_debug = false;
bool arg_gmail = false;
bool arg_no_tls = false;
string arg_user;
@ -55,6 +56,7 @@ string arg_from;
string arg_to;
int arg_count = 1;
const OptionEntry[] options = {
{ "debug", 0, 0, OptionArg.NONE, ref arg_debug, "Output debugging information", null },
{ "host", 'h', 0, OptionArg.STRING, ref arg_hostname, "SMTP server host", "<hostname-or-dotted-address>" },
{ "port", 'P', 0, OptionArg.INT, ref arg_port, "SMTP server port", "<port-number>" },
{ "gmail", 'G', 0, OptionArg.NONE, ref arg_gmail, "Gmail SMTP (no-tls ignored)", null },
@ -105,18 +107,22 @@ int main(string[] args) {
arg_count = 1;
if (arg_gmail) {
endpoint = new Geary.Endpoint("smtp.gmail.com", Geary.Smtp.ClientConnection.SECURE_SMTP_PORT,
Geary.Endpoint.Flags.TLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
endpoint = new Geary.Endpoint("smtp.gmail.com", Geary.Smtp.ClientConnection.DEFAULT_PORT_STARTTLS,
Geary.Endpoint.Flags.STARTTLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
Geary.Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
} else {
Geary.Endpoint.Flags flags = Geary.Endpoint.Flags.GRACEFUL_DISCONNECT;
if (!arg_no_tls)
flags |= Geary.Endpoint.Flags.TLS;
flags |= Geary.Endpoint.Flags.SSL;
endpoint = new Geary.Endpoint(arg_hostname, (uint16) arg_port, flags,
Geary.Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
}
stdout.printf("Enabling debug: %s\n", arg_debug.to_string());
if (arg_debug)
Geary.Logging.log_to(stdout);
credentials = new Geary.Credentials(arg_user, arg_pass);
composed_email = new Geary.ComposedEmail(new DateTime.now_local(),

View file

@ -293,7 +293,7 @@
</packing>
</child>
<child>
<object class="GtkCheckButton" id="imap tls">
<object class="GtkCheckButton" id="imap ssl">
<property name="label" translatable="yes">SS_L/TLS encryption</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
@ -398,7 +398,7 @@
</packing>
</child>
<child>
<object class="GtkCheckButton" id="smtp tls">
<object class="GtkCheckButton" id="smtp ssl">
<property name="label" translatable="yes">SS_L/TLS encryption</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>