static void next_smtp(Email *e) { e->smtp_state = 0; e->internal_state = 0; DBG("Next queued call"); e->ops = eina_list_remove_list(e->ops, e->ops); if (e->current == EMAIL_OP_SEND) e->op_ids = eina_list_remove_list(e->ops, e->op_ids); if (!e->ops) { DBG("No queued calls"); e->current = 0; return; } e->current = (uintptr_t)eina_list_data_get(e->ops); if (e->cbs) e->cbs = eina_list_remove_list(e->cbs, e->cbs); switch (e->current) { case EMAIL_OP_SEND: if (!send_smtp(e)) { Email_Send_Cb cb = eina_list_data_get(e->cbs); if (cb) cb(e->op_ids->data, EINA_FALSE); next_smtp(e); } break; case EMAIL_OP_QUIT: email_write(e, EMAIL_QUIT, sizeof(EMAIL_QUIT) - 1); default: break; } }
Email_Operation * email_pop3_rset(Email *e, Email_Cb cb, const void *data) { Email_Operation *op; EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); EINA_SAFETY_ON_TRUE_RETURN_VAL(e->state != EMAIL_STATE_CONNECTED, NULL); op = email_op_new(e, EMAIL_POP_OP_RSET, cb, data); if (!email_is_blocked(e)) email_write(e, EMAIL_POP3_RSET, sizeof(EMAIL_POP3_RSET) - 1); return op; }
Email_Operation * email_pop3_list(Email *e, Email_List_Cb cb, const void *data) { Email_Operation *op; EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); EINA_SAFETY_ON_TRUE_RETURN_VAL(e->state != EMAIL_STATE_CONNECTED, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL); op = email_op_new(e, EMAIL_POP_OP_LIST, cb, data); if (!email_is_blocked(e)) email_write(e, "LIST\r\n", 6); return op; }
Eina_Bool email_stat(Email *e, Email_Stat_Cb cb) { EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE); EINA_SAFETY_ON_TRUE_RETURN_VAL(e->state != EMAIL_STATE_CONNECTED, EINA_FALSE); e->cbs = eina_list_append(e->cbs, cb); if (!e->ops) { e->current = EMAIL_OP_STAT; email_write(e, "STAT\r\n", 6); } e->ops = eina_list_append(e->ops, (uintptr_t*)EMAIL_OP_STAT); return EINA_TRUE; }
Eina_Bool email_rset(Email *e, Email_Cb cb) { EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE); EINA_SAFETY_ON_TRUE_RETURN_VAL(e->state != EMAIL_STATE_CONNECTED, EINA_FALSE); e->cbs = eina_list_append(e->cbs, cb); if (!e->current) { e->current = EMAIL_OP_RSET; email_write(e, EMAIL_POP3_RSET, sizeof(EMAIL_POP3_RSET) - 1); } else e->ops = eina_list_append(e->ops, (uintptr_t*)EMAIL_OP_RSET); return EINA_TRUE; }
Eina_Bool email_quit_pop(Email *e, Ecore_Cb cb) { EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE); EINA_SAFETY_ON_TRUE_RETURN_VAL(e->state != EMAIL_STATE_CONNECTED, EINA_FALSE); if (!e->current) { e->current = EMAIL_OP_QUIT; email_write(e, "QUIT\r\n", 6); } else e->ops = eina_list_append(e->ops, (uintptr_t*)EMAIL_OP_QUIT); e->cbs = eina_list_append(e->cbs, cb); return EINA_TRUE; }
Eina_Bool upgrade_smtp(Email *e, int type __UNUSED__, Ecore_Con_Event_Server_Upgrade *ev) { char *buf; size_t size; if (e != ecore_con_server_data_get(ev->server)) return ECORE_CALLBACK_PASS_ON; e->state++; size = sizeof(char) * (sizeof("EHLO \r\n") + strlen(e->features.smtp_features.domain)); buf = alloca(size); snprintf(buf, size, "EHLO %s\r\n", e->features.smtp_features.domain); email_write(e, buf, size - 1); return ECORE_CALLBACK_RENEW; }
Email_Operation * email_pop3_delete(Email *e, unsigned int id, Email_Cb cb, const void *data) { char buf[64]; Email_Operation *op; EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); EINA_SAFETY_ON_TRUE_RETURN_VAL(e->state != EMAIL_STATE_CONNECTED, NULL); op = email_op_new(e, EMAIL_POP_OP_DELE, cb, data); if (!email_is_blocked(e)) { snprintf(buf, sizeof(buf), EMAIL_POP3_DELE, id); email_write(e, buf, strlen(buf)); } else op->opdata = (uintptr_t*)(unsigned long)id; return op; }
Eina_Bool email_retrieve(Email *e, unsigned int id, Email_Retr_Cb cb) { char buf[64]; EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE); EINA_SAFETY_ON_TRUE_RETURN_VAL(e->state != EMAIL_STATE_CONNECTED, EINA_FALSE); e->cbs = eina_list_append(e->cbs, cb); if (!e->current) { e->current = EMAIL_OP_RETR; snprintf(buf, sizeof(buf), EMAIL_POP3_RETR, id); email_write(e, buf, strlen(buf)); } else { e->op_ids = eina_list_append(e->op_ids, (uintptr_t*)id); e->ops = eina_list_append(e->ops, (uintptr_t*)EMAIL_OP_RETR); } return EINA_TRUE; }
static void next_smtp(Email *e) { char buf[64]; if (e->buf) return; if (!e->ops) { e->current = 0; return; } DBG("Next queued call"); e->current = (uintptr_t)e->ops->data; e->ops = eina_list_remove_list(e->ops, e->ops); switch (e->current) { case EMAIL_OP_STAT: email_write(e, EMAIL_POP3_STAT, sizeof(EMAIL_POP3_STAT) - 1); break; case EMAIL_OP_LIST: email_write(e, EMAIL_POP3_LIST, sizeof(EMAIL_POP3_LIST) - 1); break; case EMAIL_OP_RSET: email_write(e, EMAIL_POP3_RSET, sizeof(EMAIL_POP3_RSET) - 1); break; case EMAIL_OP_DELE: snprintf(buf, sizeof(buf), EMAIL_POP3_DELE, (uintptr_t)e->op_ids->data); e->op_ids = eina_list_remove_list(e->op_ids, e->op_ids); email_write(e, buf, strlen(buf)); break; case EMAIL_OP_RETR: snprintf(buf, sizeof(buf), EMAIL_POP3_RETR, (uintptr_t)e->op_ids->data); e->op_ids = eina_list_remove_list(e->op_ids, e->op_ids); email_write(e, buf, strlen(buf)); break; case EMAIL_OP_QUIT: email_write(e, EMAIL_POP3_QUIT, sizeof(EMAIL_POP3_QUIT) - 1); break; default: break; } }
void email_login_pop(Email *e, Ecore_Con_Event_Server_Data *ev) { char *buf; size_t size; switch (e->state) { case EMAIL_STATE_SSL: if (!email_op_ok(ev->data, ev->size)) { ERR("Could not create secure connection!"); ecore_con_server_del(ev->server); return; } ecore_con_ssl_server_upgrade(e->svr, ECORE_CON_USE_MIXED); ecore_con_ssl_server_verify_basic(e->svr); e->flags = ECORE_CON_USE_MIXED; return; case EMAIL_STATE_INIT: if (!email_op_ok(ev->data, ev->size)) { ERR("Not a POP3 server!"); ecore_con_server_del(ev->server); return; } if (ev->size > 20) { const unsigned char *end; end = memrchr(ev->data + 3, '>', ev->size - 3); if (end) { const unsigned char *start; start = memrchr(ev->data + 3, '<', end - (unsigned char*)ev->data); if (start) { e->features.pop_features.apop = EINA_TRUE; e->features.pop_features.apop_str = eina_binbuf_new(); eina_binbuf_append_length(e->features.pop_features.apop_str, start, end - start + 1); } } } if (e->secure && (!e->flags)) { email_write(e, "STLS\r\n", sizeof("STLS\r\n") - 1); e->state++; return; } e->state = EMAIL_STATE_USER; ev = NULL; case EMAIL_STATE_USER: if (!ev) { unsigned char digest[16]; char md5buf[33]; if (!e->features.pop_features.apop) { INF("Beginning AUTH PLAIN"); size = sizeof(char) * (sizeof("USER ") - 1 + sizeof("\r\n") - 1 + strlen(e->username)) + 1; buf = alloca(size); snprintf(buf, size, "USER %s\r\n", e->username); email_write(e, buf, size - 1); return; } INF("Beginning AUTH APOP"); e->state++; eina_binbuf_append_length(e->features.pop_features.apop_str, (unsigned char*)e->password, strlen(e->password)); md5_buffer((char*)eina_binbuf_string_get(e->features.pop_features.apop_str), eina_binbuf_length_get(e->features.pop_features.apop_str), digest); email_md5_digest_to_str(digest, md5buf); size = sizeof(char) * (sizeof("APOP ") - 1 + sizeof("\r\n") - 1 + strlen(e->username)) + sizeof(md5buf); buf = alloca(size); snprintf(buf, size, "APOP %s %s\r\n", e->username, md5buf); email_write(e, buf, size - 1); return; } if (!email_op_ok(ev->data, ev->size)) { ERR("Username invalid!"); ecore_con_server_del(e->svr); return; } size = sizeof(char) * (sizeof("PASS ") - 1 + sizeof("\r\n") - 1 + strlen(e->password)) + 1; buf = alloca(size); snprintf(buf, size, "PASS %s\r\n", e->password); DBG("Sending password"); ecore_con_server_send(e->svr, buf, size - 1); e->state++; return; case EMAIL_STATE_PASS: if (!email_op_ok(ev->data, ev->size)) { ERR("Credentials invalid!"); ecore_con_server_del(e->svr); return; } INF("Logged in successfully!"); e->state++; ecore_event_add(EMAIL_EVENT_CONNECTED, e, (Ecore_End_Cb)email_fake_free, NULL); default: break; } }
Eina_Bool send_smtp(Email *e) { char *buf; size_t size; Email_Message *msg; Email_Contact *ec; Eina_Strbuf *bbuf; e->current = EMAIL_OP_SEND; msg = e->op_ids->data; switch (e->smtp_state) { case 0: e->smtp_state++; case EMAIL_SMTP_STATE_FROM: if ((!msg->from) && (!msg->sender)) { char buf[1024]; snprintf(buf, sizeof(buf), "%s@%s", e->username, e->features.smtp_features.domain); msg->sender = email_contact_new(buf); } ec = msg->sender; size = sizeof(char) * (sizeof(EMAIL_SMTP_FROM) + strlen(ec->address)) - 2; buf = alloca(size); snprintf(buf, size, EMAIL_SMTP_FROM, ec->address); email_write(e, buf, size - 1); e->smtp_state++; e->internal_state = 0; break; case EMAIL_SMTP_STATE_TO: ec = eina_list_nth(msg->recipients, e->internal_state++); if (!ec) { e->smtp_state++; e->internal_state = 0; return send_smtp(e); } size = sizeof(char) * (sizeof(EMAIL_SMTP_TO) + strlen(ec->address)) - 2; buf = alloca(size); snprintf(buf, size, EMAIL_SMTP_TO, ec->address); email_write(e, buf, size - 1); break; case EMAIL_SMTP_STATE_DATA: email_write(e, EMAIL_SMTP_DATA, sizeof(EMAIL_SMTP_DATA) - 1); e->smtp_state++; e->internal_state = 0; break; default: bbuf = email_message_serialize(msg); e->smtp_state++; if (bbuf) { email_write(e, eina_strbuf_string_get(bbuf), eina_strbuf_length_get(bbuf)); eina_strbuf_free(bbuf); } else return EINA_FALSE; } return EINA_TRUE; }