1 #ifndef IMAPC_CLIENT_H 2 #define IMAPC_CLIENT_H 3 4 #include "net.h" 5 #include "iostream-ssl.h" 6 7 /* IMAP RFC defines this to be at least 30 minutes. */ 8 #define IMAPC_DEFAULT_MAX_IDLE_TIME (60*29) 9 10 enum imapc_command_state { 11 IMAPC_COMMAND_STATE_OK = 0, 12 IMAPC_COMMAND_STATE_NO, 13 IMAPC_COMMAND_STATE_BAD, 14 /* Authentication to IMAP server failed (NO or BAD) */ 15 IMAPC_COMMAND_STATE_AUTH_FAILED, 16 /* Client was unexpectedly disconnected. */ 17 IMAPC_COMMAND_STATE_DISCONNECTED 18 }; 19 extern const char *imapc_command_state_names[]; 20 21 enum imapc_capability { 22 IMAPC_CAPABILITY_SASL_IR = 0x01, 23 IMAPC_CAPABILITY_LITERALPLUS = 0x02, 24 IMAPC_CAPABILITY_QRESYNC = 0x04, 25 IMAPC_CAPABILITY_IDLE = 0x08, 26 IMAPC_CAPABILITY_UIDPLUS = 0x10, 27 IMAPC_CAPABILITY_AUTH_PLAIN = 0x20, 28 IMAPC_CAPABILITY_STARTTLS = 0x40, 29 IMAPC_CAPABILITY_X_GM_EXT_1 = 0x80, 30 IMAPC_CAPABILITY_CONDSTORE = 0x100, 31 IMAPC_CAPABILITY_NAMESPACE = 0x200, 32 IMAPC_CAPABILITY_UNSELECT = 0x400, 33 IMAPC_CAPABILITY_ESEARCH = 0x800, 34 IMAPC_CAPABILITY_WITHIN = 0x1000, 35 IMAPC_CAPABILITY_QUOTA = 0x2000, 36 IMAPC_CAPABILITY_ID = 0x4000, 37 IMAPC_CAPABILITY_SAVEDATE = 0x8000, 38 39 IMAPC_CAPABILITY_IMAP4REV1 = 0x40000000 40 }; 41 struct imapc_capability_name { 42 const char *name; 43 enum imapc_capability capability; 44 }; 45 extern const struct imapc_capability_name imapc_capability_names[]; 46 47 enum imapc_command_flags { 48 /* The command changes the selected mailbox (SELECT, EXAMINE) */ 49 IMAPC_COMMAND_FLAG_SELECT = 0x01, 50 /* The command is sent to server before login (or is the login 51 command itself). Non-prelogin commands will be queued until login 52 is successful. */ 53 IMAPC_COMMAND_FLAG_PRELOGIN = 0x02, 54 /* Allow command to be automatically retried if disconnected before it 55 finishes. */ 56 IMAPC_COMMAND_FLAG_RETRIABLE = 0x04, 57 /* This is the LOGOUT command. Use a small timeout for it. */ 58 IMAPC_COMMAND_FLAG_LOGOUT = 0x08, 59 /* Command is being resent after a reconnection. */ 60 IMAPC_COMMAND_FLAG_RECONNECTED = 0x10 61 }; 62 63 enum imapc_client_ssl_mode { 64 IMAPC_CLIENT_SSL_MODE_NONE, 65 IMAPC_CLIENT_SSL_MODE_IMMEDIATE, 66 IMAPC_CLIENT_SSL_MODE_STARTTLS 67 }; 68 69 #define IMAPC_DEFAULT_CONNECT_TIMEOUT_MSECS (1000*30) 70 #define IMAPC_DEFAULT_COMMAND_TIMEOUT_MSECS (1000*60*5) 71 #define IMAPC_DEFAULT_MAX_LINE_LENGTH (SIZE_MAX) 72 73 struct imapc_throttling_settings { 74 unsigned int init_msecs; 75 unsigned int max_msecs; 76 unsigned int shrink_min_msecs; 77 }; 78 79 struct imapc_client_settings { 80 const char *host; 81 in_port_t port; 82 83 const char *master_user; 84 const char *username; 85 const char *password; 86 /* Space-separated list of SASL mechanisms to try (in the specified 87 order). The default is to use only LOGIN command or SASL PLAIN. */ 88 const char *sasl_mechanisms; 89 bool use_proxyauth; /* Use Sun/Oracle PROXYAUTH command */ 90 unsigned int max_idle_time; 91 /* If ID capability is advertised, send a unique "x-session-ext-id", 92 which begins with this prefix. */ 93 const char *session_id_prefix; 94 95 const char *dns_client_socket_path; 96 const char *temp_path_prefix; 97 struct ssl_iostream_settings ssl_set; 98 99 enum imapc_client_ssl_mode ssl_mode; 100 101 const char *rawlog_dir; 102 bool debug; 103 104 /* Timeout for logging in. 0 = default. */ 105 unsigned int connect_timeout_msecs; 106 /* Number of retries, -1 = infinity */ 107 unsigned int connect_retry_count; 108 /* Interval between retries, must be > 0 if retries > 0 */ 109 unsigned int connect_retry_interval_msecs; 110 111 /* Timeout for IMAP commands. Reset every time more data is being 112 sent or received. 0 = default. */ 113 unsigned int cmd_timeout_msecs; 114 115 /* Maximum allowed line length (not including literals read as 116 streams). 0 = unlimited. */ 117 size_t max_line_length; 118 119 struct imapc_throttling_settings throttle_set; 120 }; 121 122 struct imapc_command_reply { 123 enum imapc_command_state state; 124 /* "[RESP TEXT]" produces key=RESP, value=TEXT. 125 "[RESP]" produces key=RESP, value=NULL 126 otherwise both are NULL */ 127 const char *resp_text_key, *resp_text_value; 128 /* The full tagged reply, including [RESP TEXT]. */ 129 const char *text_full; 130 /* Tagged reply text without [RESP TEXT] */ 131 const char *text_without_resp; 132 }; 133 134 struct imapc_arg_file { 135 /* file descriptor containing the value */ 136 int fd; 137 138 /* parent_arg.list[list_idx] points to the IMAP_ARG_LITERAL_SIZE 139 argument */ 140 const struct imap_arg *parent_arg; 141 unsigned int list_idx; 142 }; 143 144 struct imapc_untagged_reply { 145 /* name of the untagged reply, e.g. EXISTS */ 146 const char *name; 147 /* number at the beginning of the reply, or 0 if there wasn't any. 148 Set for EXISTS, EXPUNGE, etc. */ 149 uint32_t num; 150 /* the rest of the reply can be read from these args. */ 151 const struct imap_arg *args; 152 /* arguments whose contents are stored into files. only 153 "FETCH (BODY[" arguments can be here. */ 154 const struct imapc_arg_file *file_args; 155 unsigned int file_args_count; 156 157 /* "* OK [RESP TEXT]" produces key=RESP, value=TEXT. 158 "* OK [RESP]" produces key=RESP, value=NULL 159 otherwise both are NULL */ 160 const char *resp_text_key, *resp_text_value; 161 162 /* If this reply occurred while a mailbox was selected, this contains 163 the mailbox's untagged_context. */ 164 void *untagged_box_context; 165 }; 166 167 enum imapc_state_change_event { 168 IMAPC_STATE_CHANGE_AUTH_OK, 169 IMAPC_STATE_CHANGE_AUTH_FAILED, 170 }; 171 172 /* Called when tagged reply is received for command. */ 173 typedef void imapc_command_callback_t(const struct imapc_command_reply *reply, 174 void *context); 175 /* Called each time untagged input is received. */ 176 typedef void imapc_untagged_callback_t(const struct imapc_untagged_reply *reply, 177 void *context); 178 typedef void imapc_state_change_callback_t(void *context, 179 enum imapc_state_change_event event, 180 const char *error); 181 182 struct imapc_client * 183 imapc_client_init(const struct imapc_client_settings *set, 184 struct event *event_parent); 185 void imapc_client_disconnect(struct imapc_client *client); 186 void imapc_client_deinit(struct imapc_client **client); 187 188 /* Set login callback, must be set before calling other commands. 189 This is called only for the first login, not for any reconnects or if there 190 are multiple connections created. */ 191 void 192 imapc_client_set_login_callback(struct imapc_client *client, 193 imapc_command_callback_t *callback, void *context); 194 /* Explicitly login to server (also done automatically). */ 195 void imapc_client_login(struct imapc_client *client); 196 /* Send a LOGOUT and wait for disconnection. */ 197 void imapc_client_logout(struct imapc_client *client); 198 199 struct imapc_command * 200 imapc_client_cmd(struct imapc_client *client, 201 imapc_command_callback_t *callback, void *context); 202 void imapc_command_set_flags(struct imapc_command *cmd, 203 enum imapc_command_flags flags); 204 bool imapc_command_connection_is_selected(struct imapc_command *cmd); 205 void imapc_command_send(struct imapc_command *cmd, const char *cmd_str); 206 void imapc_command_sendf(struct imapc_command *cmd, const char *cmd_fmt, ...) 207 ATTR_FORMAT(2, 3); 208 void imapc_command_sendvf(struct imapc_command *cmd, 209 const char *cmd_fmt, va_list args) ATTR_FORMAT(2, 0); 210 const char *imapc_command_get_tag(struct imapc_command *cmd); 211 void imapc_command_abort(struct imapc_command **cmd); 212 213 void imapc_client_register_untagged(struct imapc_client *client, 214 imapc_untagged_callback_t *callback, 215 void *context); 216 217 void imapc_client_run(struct imapc_client *client); 218 void imapc_client_stop(struct imapc_client *client); 219 bool imapc_client_is_running(struct imapc_client *client); 220 221 struct imapc_client_mailbox * 222 imapc_client_mailbox_open(struct imapc_client *client, 223 void *untagged_box_context); 224 void imapc_client_mailbox_set_reopen_cb(struct imapc_client_mailbox *box, 225 void (*callback)(void *context), 226 void *context); 227 void imapc_client_mailbox_close(struct imapc_client_mailbox **box); 228 bool imapc_client_mailbox_can_reconnect(struct imapc_client_mailbox *box); 229 void imapc_client_mailbox_reconnect(struct imapc_client_mailbox *box, 230 const char *errmsg); 231 struct imapc_command * 232 imapc_client_mailbox_cmd(struct imapc_client_mailbox *box, 233 imapc_command_callback_t *callback, void *context); 234 struct imapc_msgmap * 235 imapc_client_mailbox_get_msgmap(struct imapc_client_mailbox *box); 236 237 void imapc_client_mailbox_idle(struct imapc_client_mailbox *box); 238 bool imapc_client_mailbox_is_opened(struct imapc_client_mailbox *box); 239 240 int imapc_client_get_capabilities(struct imapc_client *client, 241 enum imapc_capability *capabilities_r); 242 243 int imapc_client_create_temp_fd(struct imapc_client *client, 244 const char **path_r); 245 246 void imapc_client_register_state_change_callback(struct imapc_client *client, 247 imapc_state_change_callback_t *cb, 248 void *context); 249 250 #endif 251