-rw-r--r-- | noncore/net/mail/imapwrapper.cpp | 4 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/imapwrapper.cpp | 4 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mailwrapper.cpp | 12 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mailwrapper.h | 4 | ||||
-rw-r--r-- | noncore/net/mail/mailwrapper.cpp | 12 | ||||
-rw-r--r-- | noncore/net/mail/mailwrapper.h | 4 |
6 files changed, 32 insertions, 8 deletions
diff --git a/noncore/net/mail/imapwrapper.cpp b/noncore/net/mail/imapwrapper.cpp index b253b49..0ce2c6c 100644 --- a/noncore/net/mail/imapwrapper.cpp +++ b/noncore/net/mail/imapwrapper.cpp @@ -1,771 +1,773 @@ #include <stdlib.h> #include "imapwrapper.h" #include "mailtypes.h" #include <libetpan/mailimap.h> IMAPwrapper::IMAPwrapper( IMAPaccount *a ) : AbstractMail() { account = a; m_imap = 0; } IMAPwrapper::~IMAPwrapper() { logout(); } void IMAPwrapper::imap_progress( size_t current, size_t maximum ) { qDebug( "IMAP: %i of %i", current, maximum ); } void IMAPwrapper::login() { const char *server, *user, *pass; uint16_t port; int err = MAILIMAP_NO_ERROR; /* we are connected this moment */ /* TODO: setup a timer holding the line or if connection closed - delete the value */ if (m_imap) { mailstream_flush(m_imap->imap_stream); return; } server = account->getServer().latin1(); port = account->getPort().toUInt(); user = account->getUser().latin1(); pass = account->getPassword().latin1(); m_imap = mailimap_new( 20, &imap_progress ); /* connect */ if (account->getSSL()) { err = mailimap_ssl_connect( m_imap, (char*)server, port ); } else { err = mailimap_socket_connect( m_imap, (char*)server, port ); } if ( err != MAILIMAP_NO_ERROR && err != MAILIMAP_NO_ERROR_AUTHENTICATED && err != MAILIMAP_NO_ERROR_NON_AUTHENTICATED ) { qDebug("error connecting server: %s",m_imap->imap_response); mailimap_free( m_imap ); m_imap = 0; return; } /* login */ err = mailimap_login_simple( m_imap, (char*)user, (char*)pass ); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error logging in imap: %s",m_imap->imap_response); err = mailimap_close( m_imap ); mailimap_free( m_imap ); m_imap = 0; } } void IMAPwrapper::logout() { int err = MAILIMAP_NO_ERROR; if (!m_imap) return; err = mailimap_logout( m_imap ); err = mailimap_close( m_imap ); mailimap_free( m_imap ); m_imap = 0; } void IMAPwrapper::listMessages(const QString&mailbox,QList<RecMail> &target ) { const char *mb; int err = MAILIMAP_NO_ERROR; clist *result; clistcell *current; // mailimap_fetch_att *fetchAtt,*fetchAttFlags,*fetchAttDate,*fetchAttSize; mailimap_fetch_type *fetchType; mailimap_set *set; mb = mailbox.latin1(); login(); if (!m_imap) { return; } /* select mailbox READONLY for operations */ err = mailimap_examine( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox: %s",m_imap->imap_response); return; } int last = m_imap->imap_selection_info->sel_exists; if (last == 0) { qDebug("mailbox has no mails"); return; } result = clist_new(); /* the range has to start at 1!!! not with 0!!!! */ set = mailimap_set_new_interval( 1, last ); fetchType = mailimap_fetch_type_new_fetch_att_list_empty(); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_envelope()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_flags()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_internaldate()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_rfc822_size()); err = mailimap_fetch( m_imap, set, fetchType, &result ); mailimap_set_free( set ); mailimap_fetch_type_free( fetchType ); QString date,subject,from; if ( err == MAILIMAP_NO_ERROR ) { mailimap_msg_att * msg_att; int i = 0; for (current = clist_begin(result); current != 0; current=clist_next(current)) { ++i; msg_att = (mailimap_msg_att*)current->data; RecMail*m = parse_list_result(msg_att); if (m) { m->setNumber(i); m->setMbox(mailbox); m->setWrapper(this); target.append(m); } } } else { qDebug("Error fetching headers: %s",m_imap->imap_response); } mailimap_fetch_list_free(result); } QList<Folder>* IMAPwrapper::listFolders() { const char *path, *mask; int err = MAILIMAP_NO_ERROR; clist *result; clistcell *current; QList<Folder> * folders = new QList<Folder>(); folders->setAutoDelete( false ); login(); if (!m_imap) { return folders; } /* * First we have to check for INBOX 'cause it sometimes it's not inside the path. * We must not forget to filter them out in next loop! * it seems like ugly code. and yes - it is ugly code. but the best way. */ QString temp; mask = "INBOX" ; result = clist_new(); mailimap_mailbox_list *list; err = mailimap_list( m_imap, (char*)"", (char*)mask, &result ); if ( err == MAILIMAP_NO_ERROR ) { current = result->first; for ( int i = result->count; i > 0; i-- ) { list = (mailimap_mailbox_list *) current->data; // it is better use the deep copy mechanism of qt itself // instead of using strdup! temp = list->mb_name; folders->append( new IMAPFolder(temp)); current = current->next; } } else { qDebug("error fetching folders: %s",m_imap->imap_response); } mailimap_list_result_free( result ); /* * second stage - get the other then inbox folders */ mask = "*" ; path = account->getPrefix().latin1(); if (!path) path = ""; result = clist_new(); qDebug(path); bool selectable = true; mailimap_mbx_list_flags*bflags; err = mailimap_list( m_imap, (char*)path, (char*)mask, &result ); if ( err == MAILIMAP_NO_ERROR ) { current = result->first; for ( current=clist_begin(result);current!=NULL;current=clist_next(current)) { list = (mailimap_mailbox_list *) current->data; // it is better use the deep copy mechanism of qt itself // instead of using strdup! temp = list->mb_name; if (temp.lower()=="inbox") continue; + if (temp.lower()==account->getPrefix().lower()) + continue; if ( (bflags = list->mb_flag) ) { selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&& bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT); } - folders->append(new IMAPFolder(temp,selectable)); + folders->append(new IMAPFolder(temp,selectable,account->getPrefix())); } } else { qDebug("error fetching folders %s",m_imap->imap_response); } mailimap_list_result_free( result ); return folders; } RecMail*IMAPwrapper::parse_list_result(mailimap_msg_att* m_att) { RecMail * m = 0; mailimap_msg_att_item *item=0; clistcell *current,*c,*cf; mailimap_msg_att_dynamic*flist; mailimap_flag_fetch*cflag; int size; QBitArray mFlags(7); QStringList addresslist; if (!m_att) { return m; } m = new RecMail(); for (c = clist_begin(m_att->att_list); c!=NULL;c=clist_next(c) ) { current = c; size = 0; item = (mailimap_msg_att_item*)current->data; if (item->att_type!=MAILIMAP_MSG_ATT_ITEM_STATIC) { flist = (mailimap_msg_att_dynamic*)item->att_data.att_dyn; if (!flist->att_list) { continue; } cf = flist->att_list->first; for (cf = clist_begin(flist->att_list); cf!=NULL; cf = clist_next(cf)) { cflag = (mailimap_flag_fetch*)cf->data; if (cflag->fl_type==MAILIMAP_FLAG_FETCH_OTHER && cflag->fl_flag!=0) { switch (cflag->fl_flag->fl_type) { case MAILIMAP_FLAG_ANSWERED: /* \Answered flag */ mFlags.setBit(FLAG_ANSWERED); break; case MAILIMAP_FLAG_FLAGGED: /* \Flagged flag */ mFlags.setBit(FLAG_FLAGGED); break; case MAILIMAP_FLAG_DELETED: /* \Deleted flag */ mFlags.setBit(FLAG_DELETED); break; case MAILIMAP_FLAG_SEEN: /* \Seen flag */ mFlags.setBit(FLAG_SEEN); break; case MAILIMAP_FLAG_DRAFT: /* \Draft flag */ mFlags.setBit(FLAG_DRAFT); break; case MAILIMAP_FLAG_KEYWORD: /* keyword flag */ break; case MAILIMAP_FLAG_EXTENSION: /* \extension flag */ break; default: break; } } else if (cflag->fl_type==MAILIMAP_FLAG_FETCH_RECENT) { mFlags.setBit(FLAG_RECENT); } } continue; } if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_ENVELOPE) { mailimap_envelope * head = item->att_data.att_static->att_data.att_env; m->setDate(head->env_date); m->setSubject(head->env_subject); if (head->env_from!=NULL) { addresslist = address_list_to_stringlist(head->env_from->frm_list); if (addresslist.count()) { m->setFrom(addresslist.first()); } } if (head->env_to!=NULL) { addresslist = address_list_to_stringlist(head->env_to->to_list); m->setTo(addresslist); } if (head->env_cc!=NULL) { addresslist = address_list_to_stringlist(head->env_cc->cc_list); m->setCC(addresslist); } if (head->env_bcc!=NULL) { addresslist = address_list_to_stringlist(head->env_bcc->bcc_list); m->setBcc(addresslist); } if (head->env_reply_to!=NULL) { addresslist = address_list_to_stringlist(head->env_reply_to->rt_list); if (addresslist.count()) { m->setReplyto(addresslist.first()); } } m->setMsgid(QString(head->env_message_id)); } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_INTERNALDATE) { mailimap_date_time*d = item->att_data.att_static->att_data.att_internal_date; #if 0 QDateTime da(QDate(d->dt_year,d->dt_month,d->dt_day),QTime(d->dt_hour,d->dt_min,d->dt_sec)); qDebug("%i %i %i - %i %i %i",d->dt_year,d->dt_month,d->dt_day,d->dt_hour,d->dt_min,d->dt_sec); qDebug(da.toString()); #endif } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_RFC822_SIZE) { size = item->att_data.att_static->att_data.att_rfc822_size; } } /* msg is already deleted */ if (mFlags.testBit(FLAG_DELETED) && m) { delete m; m = 0; } if (m) { m->setFlags(mFlags); m->setMsgsize(size); } return m; } RecBody IMAPwrapper::fetchBody(const RecMail&mail) { RecBody body; const char *mb; int err = MAILIMAP_NO_ERROR; clist *result; clistcell *current; mailimap_fetch_att *fetchAtt; mailimap_fetch_type *fetchType; mailimap_set *set; mailimap_body*body_desc; mb = mail.getMbox().latin1(); login(); if (!m_imap) { return body; } err = mailimap_select( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox: %s",m_imap->imap_response); return body; } result = clist_new(); /* the range has to start at 1!!! not with 0!!!! */ set = mailimap_set_new_interval( mail.getNumber(),mail.getNumber() ); fetchAtt = mailimap_fetch_att_new_bodystructure(); fetchType = mailimap_fetch_type_new_fetch_att(fetchAtt); err = mailimap_fetch( m_imap, set, fetchType, &result ); mailimap_set_free( set ); mailimap_fetch_type_free( fetchType ); if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) { mailimap_msg_att * msg_att; msg_att = (mailimap_msg_att*)current->data; mailimap_msg_att_item*item = (mailimap_msg_att_item*)msg_att->att_list->first->data; body_desc = item->att_data.att_static->att_data.att_body; if (body_desc->bd_type==MAILIMAP_BODY_1PART) { searchBodyText(mail,body_desc->bd_data.bd_body_1part,body); } else if (body_desc->bd_type==MAILIMAP_BODY_MPART) { qDebug("Mulitpart mail"); searchBodyText(mail,body_desc->bd_data.bd_body_mpart,body); } } else { qDebug("error fetching body: %s",m_imap->imap_response); } mailimap_fetch_list_free(result); return body; } /* this routine is just called when the mail has only ONE part. for filling the parts of a multi-part-message there are other routines 'cause we can not simply fetch the whole body. */ void IMAPwrapper::searchBodyText(const RecMail&mail,mailimap_body_type_1part*mailDescription,RecBody&target_body) { if (!mailDescription) { return; } QString sub,body_text; RecPart singlePart; QValueList<int> path; fillSinglePart(singlePart,mailDescription); switch (mailDescription->bd_type) { case MAILIMAP_BODY_TYPE_1PART_MSG: path.append(1); body_text = fetchPart(mail,path,true); target_body.setBodytext(body_text); target_body.setDescription(singlePart); break; case MAILIMAP_BODY_TYPE_1PART_TEXT: qDebug("Mediatype single: %s",mailDescription->bd_data.bd_type_text->bd_media_text); path.append(1); body_text = fetchPart(mail,path,true); target_body.setBodytext(body_text); target_body.setDescription(singlePart); break; case MAILIMAP_BODY_TYPE_1PART_BASIC: qDebug("Single attachment"); target_body.setBodytext(""); target_body.addPart(singlePart); break; default: break; } return; } QStringList IMAPwrapper::address_list_to_stringlist(clist*list) { QStringList l; QString from; bool named_from; clistcell *current = NULL; mailimap_address * current_address=NULL; if (!list) { return l; } unsigned int count = 0; for (current=clist_begin(list);current!= NULL;current=clist_next(current)) { from = ""; named_from = false; current_address=(mailimap_address*)current->data; if (current_address->ad_personal_name){ from+=QString(current_address->ad_personal_name); from+=" "; named_from = true; } if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) { from+="<"; } if (current_address->ad_mailbox_name) { from+=QString(current_address->ad_mailbox_name); from+="@"; } if (current_address->ad_host_name) { from+=QString(current_address->ad_host_name); } if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) { from+=">"; } l.append(QString(from)); if (++count > 99) { break; } } return l; } QString IMAPwrapper::fetchPart(const RecMail&mail,const QValueList<int>&path,bool internal_call) { QString body(""); const char*mb; int err; mailimap_fetch_type *fetchType; mailimap_set *set; clistcell*current,*cur; login(); if (!m_imap) { return body; } if (!internal_call) { mb = mail.getMbox().latin1(); err = mailimap_select( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox: %s",m_imap->imap_response); return body; } } set = mailimap_set_new_single(mail.getNumber()); clist*id_list=clist_new(); for (unsigned j=0; j < path.count();++j) { uint32_t * p_id = (uint32_t *)malloc(sizeof(*p_id)); *p_id = path[j]; clist_append(id_list,p_id); } mailimap_section_part * section_part = mailimap_section_part_new(id_list); mailimap_section_spec * section_spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, NULL, section_part, NULL); mailimap_section * section = mailimap_section_new(section_spec); mailimap_fetch_att * fetch_att = mailimap_fetch_att_new_body_section(section); fetchType = mailimap_fetch_type_new_fetch_att(fetch_att); clist*result = clist_new(); err = mailimap_fetch( m_imap, set, fetchType, &result ); mailimap_set_free( set ); mailimap_fetch_type_free( fetchType ); if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) { mailimap_msg_att * msg_att; msg_att = (mailimap_msg_att*)current->data; mailimap_msg_att_item*msg_att_item; for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) { msg_att_item = (mailimap_msg_att_item*)clist_content(cur); if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { if (msg_att_item->att_data.att_static->att_type == MAILIMAP_MSG_ATT_BODY_SECTION) { char*text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = 0L; if (text) { body = QString(text); free(text); } else { body = ""; } } } } } else { qDebug("error fetching text: %s",m_imap->imap_response); } mailimap_fetch_list_free(result); return body; } void IMAPwrapper::searchBodyText(const RecMail&mail,mailimap_body_type_mpart*mailDescription,RecBody&target_body,int current_recursion,QValueList<int>recList) { /* current_recursion is for avoiding ugly mails which has a to deep body-structure */ if (!mailDescription||current_recursion==10) { return; } clistcell*current; mailimap_body*current_body; unsigned int count = 0; for (current=clist_begin(mailDescription->bd_list);current!=0;current=clist_next(current)) { /* the point in the message */ ++count; current_body = (mailimap_body*)current->data; if (current_body->bd_type==MAILIMAP_BODY_MPART) { QValueList<int>clist = recList; clist.append(count); searchBodyText(mail,current_body->bd_data.bd_body_mpart,target_body,current_recursion+1,clist); } else if (current_body->bd_type==MAILIMAP_BODY_1PART){ RecPart currentPart; fillSinglePart(currentPart,current_body->bd_data.bd_body_1part); QValueList<int>clist = recList; clist.append(count); /* important: Check for is NULL 'cause a body can be empty! */ if (currentPart.Type()=="text" && target_body.Bodytext().isNull() ) { QString body_text = fetchPart(mail,clist,true); target_body.setDescription(currentPart); target_body.setBodytext(body_text); } else { QString id(""); for (unsigned int j = 0; j < clist.count();++j) { id+=(j>0?" ":""); id+=QString("%1").arg(clist[j]); } qDebug("ID= %s",id.latin1()); currentPart.setIdentifier(id); currentPart.setPositionlist(clist); target_body.addPart(currentPart); } } } } void IMAPwrapper::fillSinglePart(RecPart&target_part,mailimap_body_type_1part*Description) { if (!Description) { return; } switch (Description->bd_type) { case MAILIMAP_BODY_TYPE_1PART_TEXT: target_part.setType("text"); fillSingleTextPart(target_part,Description->bd_data.bd_type_text); break; case MAILIMAP_BODY_TYPE_1PART_BASIC: fillSingleBasicPart(target_part,Description->bd_data.bd_type_basic); break; case MAILIMAP_BODY_TYPE_1PART_MSG: fillSingleMsgPart(target_part,Description->bd_data.bd_type_msg); break; default: break; } } void IMAPwrapper::fillSingleTextPart(RecPart&target_part,mailimap_body_type_text*which) { if (!which) { return; } QString sub; sub = which->bd_media_text; target_part.setSubtype(sub.lower()); target_part.setLines(which->bd_lines); fillBodyFields(target_part,which->bd_fields); } void IMAPwrapper::fillSingleMsgPart(RecPart&target_part,mailimap_body_type_msg*which) { if (!which) { return; } // QString sub; // sub = which->bd_media_text; // target_part.setSubtype(sub.lower()); qDebug("Message part"); /* we set this type to text/plain */ target_part.setType("text"); target_part.setSubtype("plain"); target_part.setLines(which->bd_lines); fillBodyFields(target_part,which->bd_fields); } void IMAPwrapper::fillSingleBasicPart(RecPart&target_part,mailimap_body_type_basic*which) { if (!which) { return; } QString type,sub; switch (which->bd_media_basic->med_type) { case MAILIMAP_MEDIA_BASIC_APPLICATION: type = "application"; break; case MAILIMAP_MEDIA_BASIC_AUDIO: type = "audio"; break; case MAILIMAP_MEDIA_BASIC_IMAGE: type = "image"; break; case MAILIMAP_MEDIA_BASIC_MESSAGE: type = "message"; break; case MAILIMAP_MEDIA_BASIC_VIDEO: type = "video"; break; case MAILIMAP_MEDIA_BASIC_OTHER: default: if (which->bd_media_basic->med_basic_type) { type = which->bd_media_basic->med_basic_type; } else { type = ""; } break; } if (which->bd_media_basic->med_subtype) { sub = which->bd_media_basic->med_subtype; } else { sub = ""; } qDebug("Type = %s/%s",type.latin1(),sub.latin1()); target_part.setType(type.lower()); target_part.setSubtype(sub.lower()); fillBodyFields(target_part,which->bd_fields); } void IMAPwrapper::fillBodyFields(RecPart&target_part,mailimap_body_fields*which) { if (!which) return; if (which->bd_parameter && which->bd_parameter->pa_list && which->bd_parameter->pa_list->count>0) { clistcell*cur; mailimap_single_body_fld_param*param=0; for (cur = clist_begin(which->bd_parameter->pa_list);cur!=NULL;cur=clist_next(cur)) { param = (mailimap_single_body_fld_param*)cur->data; if (param) { target_part.addParameter(QString(param->pa_name).lower(),QString(param->pa_value)); } } } mailimap_body_fld_enc*enc = which->bd_encoding; QString encoding(""); switch (enc->enc_type) { case MAILIMAP_BODY_FLD_ENC_7BIT: encoding = "7bit"; break; case MAILIMAP_BODY_FLD_ENC_8BIT: encoding = "8bit"; break; case MAILIMAP_BODY_FLD_ENC_BINARY: encoding="binary"; break; case MAILIMAP_BODY_FLD_ENC_BASE64: encoding="base64"; break; case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: encoding="quoted-printable"; break; case MAILIMAP_BODY_FLD_ENC_OTHER: default: if (enc->enc_value) { char*t=enc->enc_value; encoding=QString(enc->enc_value); enc->enc_value=0L; free(t); } } target_part.setEncoding(encoding); target_part.setSize(which->bd_size); } QString IMAPwrapper::fetchPart(const RecMail&mail,const RecPart&part) { return fetchPart(mail,part.Positionlist(),false); } void IMAPwrapper::deleteMail(const RecMail&mail) { mailimap_flag_list*flist; mailimap_set *set; mailimap_store_att_flags * store_flags; int err; login(); if (!m_imap) { return; } const char *mb = mail.getMbox().latin1(); err = mailimap_select( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox for delete: %s",m_imap->imap_response); return; } flist = mailimap_flag_list_new_empty(); mailimap_flag_list_add(flist,mailimap_flag_new_deleted()); store_flags = mailimap_store_att_flags_new_set_flags(flist); set = mailimap_set_new_single(mail.getNumber()); err = mailimap_store(m_imap,set,store_flags); mailimap_set_free( set ); mailimap_store_att_flags_free(store_flags); if (err != MAILIMAP_NO_ERROR) { qDebug("error deleting mail: %s",m_imap->imap_response); return; } qDebug("deleting mail: %s",m_imap->imap_response); /* should we realy do that at this moment? */ err = mailimap_expunge(m_imap); if (err != MAILIMAP_NO_ERROR) { qDebug("error deleting mail: %s",m_imap->imap_response); } qDebug("Delete successfull %s",m_imap->imap_response); } void IMAPwrapper::answeredMail(const RecMail&mail) { mailimap_flag_list*flist; mailimap_set *set; mailimap_store_att_flags * store_flags; int err; login(); if (!m_imap) { return; } const char *mb = mail.getMbox().latin1(); err = mailimap_select( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox for mark: %s",m_imap->imap_response); return; } flist = mailimap_flag_list_new_empty(); mailimap_flag_list_add(flist,mailimap_flag_new_answered()); store_flags = mailimap_store_att_flags_new_set_flags(flist); set = mailimap_set_new_single(mail.getNumber()); err = mailimap_store(m_imap,set,store_flags); mailimap_set_free( set ); mailimap_store_att_flags_free(store_flags); if (err != MAILIMAP_NO_ERROR) { qDebug("error marking mail: %s",m_imap->imap_response); return; } } diff --git a/noncore/net/mail/libmailwrapper/imapwrapper.cpp b/noncore/net/mail/libmailwrapper/imapwrapper.cpp index b253b49..0ce2c6c 100644 --- a/noncore/net/mail/libmailwrapper/imapwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/imapwrapper.cpp @@ -1,771 +1,773 @@ #include <stdlib.h> #include "imapwrapper.h" #include "mailtypes.h" #include <libetpan/mailimap.h> IMAPwrapper::IMAPwrapper( IMAPaccount *a ) : AbstractMail() { account = a; m_imap = 0; } IMAPwrapper::~IMAPwrapper() { logout(); } void IMAPwrapper::imap_progress( size_t current, size_t maximum ) { qDebug( "IMAP: %i of %i", current, maximum ); } void IMAPwrapper::login() { const char *server, *user, *pass; uint16_t port; int err = MAILIMAP_NO_ERROR; /* we are connected this moment */ /* TODO: setup a timer holding the line or if connection closed - delete the value */ if (m_imap) { mailstream_flush(m_imap->imap_stream); return; } server = account->getServer().latin1(); port = account->getPort().toUInt(); user = account->getUser().latin1(); pass = account->getPassword().latin1(); m_imap = mailimap_new( 20, &imap_progress ); /* connect */ if (account->getSSL()) { err = mailimap_ssl_connect( m_imap, (char*)server, port ); } else { err = mailimap_socket_connect( m_imap, (char*)server, port ); } if ( err != MAILIMAP_NO_ERROR && err != MAILIMAP_NO_ERROR_AUTHENTICATED && err != MAILIMAP_NO_ERROR_NON_AUTHENTICATED ) { qDebug("error connecting server: %s",m_imap->imap_response); mailimap_free( m_imap ); m_imap = 0; return; } /* login */ err = mailimap_login_simple( m_imap, (char*)user, (char*)pass ); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error logging in imap: %s",m_imap->imap_response); err = mailimap_close( m_imap ); mailimap_free( m_imap ); m_imap = 0; } } void IMAPwrapper::logout() { int err = MAILIMAP_NO_ERROR; if (!m_imap) return; err = mailimap_logout( m_imap ); err = mailimap_close( m_imap ); mailimap_free( m_imap ); m_imap = 0; } void IMAPwrapper::listMessages(const QString&mailbox,QList<RecMail> &target ) { const char *mb; int err = MAILIMAP_NO_ERROR; clist *result; clistcell *current; // mailimap_fetch_att *fetchAtt,*fetchAttFlags,*fetchAttDate,*fetchAttSize; mailimap_fetch_type *fetchType; mailimap_set *set; mb = mailbox.latin1(); login(); if (!m_imap) { return; } /* select mailbox READONLY for operations */ err = mailimap_examine( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox: %s",m_imap->imap_response); return; } int last = m_imap->imap_selection_info->sel_exists; if (last == 0) { qDebug("mailbox has no mails"); return; } result = clist_new(); /* the range has to start at 1!!! not with 0!!!! */ set = mailimap_set_new_interval( 1, last ); fetchType = mailimap_fetch_type_new_fetch_att_list_empty(); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_envelope()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_flags()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_internaldate()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_rfc822_size()); err = mailimap_fetch( m_imap, set, fetchType, &result ); mailimap_set_free( set ); mailimap_fetch_type_free( fetchType ); QString date,subject,from; if ( err == MAILIMAP_NO_ERROR ) { mailimap_msg_att * msg_att; int i = 0; for (current = clist_begin(result); current != 0; current=clist_next(current)) { ++i; msg_att = (mailimap_msg_att*)current->data; RecMail*m = parse_list_result(msg_att); if (m) { m->setNumber(i); m->setMbox(mailbox); m->setWrapper(this); target.append(m); } } } else { qDebug("Error fetching headers: %s",m_imap->imap_response); } mailimap_fetch_list_free(result); } QList<Folder>* IMAPwrapper::listFolders() { const char *path, *mask; int err = MAILIMAP_NO_ERROR; clist *result; clistcell *current; QList<Folder> * folders = new QList<Folder>(); folders->setAutoDelete( false ); login(); if (!m_imap) { return folders; } /* * First we have to check for INBOX 'cause it sometimes it's not inside the path. * We must not forget to filter them out in next loop! * it seems like ugly code. and yes - it is ugly code. but the best way. */ QString temp; mask = "INBOX" ; result = clist_new(); mailimap_mailbox_list *list; err = mailimap_list( m_imap, (char*)"", (char*)mask, &result ); if ( err == MAILIMAP_NO_ERROR ) { current = result->first; for ( int i = result->count; i > 0; i-- ) { list = (mailimap_mailbox_list *) current->data; // it is better use the deep copy mechanism of qt itself // instead of using strdup! temp = list->mb_name; folders->append( new IMAPFolder(temp)); current = current->next; } } else { qDebug("error fetching folders: %s",m_imap->imap_response); } mailimap_list_result_free( result ); /* * second stage - get the other then inbox folders */ mask = "*" ; path = account->getPrefix().latin1(); if (!path) path = ""; result = clist_new(); qDebug(path); bool selectable = true; mailimap_mbx_list_flags*bflags; err = mailimap_list( m_imap, (char*)path, (char*)mask, &result ); if ( err == MAILIMAP_NO_ERROR ) { current = result->first; for ( current=clist_begin(result);current!=NULL;current=clist_next(current)) { list = (mailimap_mailbox_list *) current->data; // it is better use the deep copy mechanism of qt itself // instead of using strdup! temp = list->mb_name; if (temp.lower()=="inbox") continue; + if (temp.lower()==account->getPrefix().lower()) + continue; if ( (bflags = list->mb_flag) ) { selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&& bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT); } - folders->append(new IMAPFolder(temp,selectable)); + folders->append(new IMAPFolder(temp,selectable,account->getPrefix())); } } else { qDebug("error fetching folders %s",m_imap->imap_response); } mailimap_list_result_free( result ); return folders; } RecMail*IMAPwrapper::parse_list_result(mailimap_msg_att* m_att) { RecMail * m = 0; mailimap_msg_att_item *item=0; clistcell *current,*c,*cf; mailimap_msg_att_dynamic*flist; mailimap_flag_fetch*cflag; int size; QBitArray mFlags(7); QStringList addresslist; if (!m_att) { return m; } m = new RecMail(); for (c = clist_begin(m_att->att_list); c!=NULL;c=clist_next(c) ) { current = c; size = 0; item = (mailimap_msg_att_item*)current->data; if (item->att_type!=MAILIMAP_MSG_ATT_ITEM_STATIC) { flist = (mailimap_msg_att_dynamic*)item->att_data.att_dyn; if (!flist->att_list) { continue; } cf = flist->att_list->first; for (cf = clist_begin(flist->att_list); cf!=NULL; cf = clist_next(cf)) { cflag = (mailimap_flag_fetch*)cf->data; if (cflag->fl_type==MAILIMAP_FLAG_FETCH_OTHER && cflag->fl_flag!=0) { switch (cflag->fl_flag->fl_type) { case MAILIMAP_FLAG_ANSWERED: /* \Answered flag */ mFlags.setBit(FLAG_ANSWERED); break; case MAILIMAP_FLAG_FLAGGED: /* \Flagged flag */ mFlags.setBit(FLAG_FLAGGED); break; case MAILIMAP_FLAG_DELETED: /* \Deleted flag */ mFlags.setBit(FLAG_DELETED); break; case MAILIMAP_FLAG_SEEN: /* \Seen flag */ mFlags.setBit(FLAG_SEEN); break; case MAILIMAP_FLAG_DRAFT: /* \Draft flag */ mFlags.setBit(FLAG_DRAFT); break; case MAILIMAP_FLAG_KEYWORD: /* keyword flag */ break; case MAILIMAP_FLAG_EXTENSION: /* \extension flag */ break; default: break; } } else if (cflag->fl_type==MAILIMAP_FLAG_FETCH_RECENT) { mFlags.setBit(FLAG_RECENT); } } continue; } if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_ENVELOPE) { mailimap_envelope * head = item->att_data.att_static->att_data.att_env; m->setDate(head->env_date); m->setSubject(head->env_subject); if (head->env_from!=NULL) { addresslist = address_list_to_stringlist(head->env_from->frm_list); if (addresslist.count()) { m->setFrom(addresslist.first()); } } if (head->env_to!=NULL) { addresslist = address_list_to_stringlist(head->env_to->to_list); m->setTo(addresslist); } if (head->env_cc!=NULL) { addresslist = address_list_to_stringlist(head->env_cc->cc_list); m->setCC(addresslist); } if (head->env_bcc!=NULL) { addresslist = address_list_to_stringlist(head->env_bcc->bcc_list); m->setBcc(addresslist); } if (head->env_reply_to!=NULL) { addresslist = address_list_to_stringlist(head->env_reply_to->rt_list); if (addresslist.count()) { m->setReplyto(addresslist.first()); } } m->setMsgid(QString(head->env_message_id)); } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_INTERNALDATE) { mailimap_date_time*d = item->att_data.att_static->att_data.att_internal_date; #if 0 QDateTime da(QDate(d->dt_year,d->dt_month,d->dt_day),QTime(d->dt_hour,d->dt_min,d->dt_sec)); qDebug("%i %i %i - %i %i %i",d->dt_year,d->dt_month,d->dt_day,d->dt_hour,d->dt_min,d->dt_sec); qDebug(da.toString()); #endif } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_RFC822_SIZE) { size = item->att_data.att_static->att_data.att_rfc822_size; } } /* msg is already deleted */ if (mFlags.testBit(FLAG_DELETED) && m) { delete m; m = 0; } if (m) { m->setFlags(mFlags); m->setMsgsize(size); } return m; } RecBody IMAPwrapper::fetchBody(const RecMail&mail) { RecBody body; const char *mb; int err = MAILIMAP_NO_ERROR; clist *result; clistcell *current; mailimap_fetch_att *fetchAtt; mailimap_fetch_type *fetchType; mailimap_set *set; mailimap_body*body_desc; mb = mail.getMbox().latin1(); login(); if (!m_imap) { return body; } err = mailimap_select( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox: %s",m_imap->imap_response); return body; } result = clist_new(); /* the range has to start at 1!!! not with 0!!!! */ set = mailimap_set_new_interval( mail.getNumber(),mail.getNumber() ); fetchAtt = mailimap_fetch_att_new_bodystructure(); fetchType = mailimap_fetch_type_new_fetch_att(fetchAtt); err = mailimap_fetch( m_imap, set, fetchType, &result ); mailimap_set_free( set ); mailimap_fetch_type_free( fetchType ); if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) { mailimap_msg_att * msg_att; msg_att = (mailimap_msg_att*)current->data; mailimap_msg_att_item*item = (mailimap_msg_att_item*)msg_att->att_list->first->data; body_desc = item->att_data.att_static->att_data.att_body; if (body_desc->bd_type==MAILIMAP_BODY_1PART) { searchBodyText(mail,body_desc->bd_data.bd_body_1part,body); } else if (body_desc->bd_type==MAILIMAP_BODY_MPART) { qDebug("Mulitpart mail"); searchBodyText(mail,body_desc->bd_data.bd_body_mpart,body); } } else { qDebug("error fetching body: %s",m_imap->imap_response); } mailimap_fetch_list_free(result); return body; } /* this routine is just called when the mail has only ONE part. for filling the parts of a multi-part-message there are other routines 'cause we can not simply fetch the whole body. */ void IMAPwrapper::searchBodyText(const RecMail&mail,mailimap_body_type_1part*mailDescription,RecBody&target_body) { if (!mailDescription) { return; } QString sub,body_text; RecPart singlePart; QValueList<int> path; fillSinglePart(singlePart,mailDescription); switch (mailDescription->bd_type) { case MAILIMAP_BODY_TYPE_1PART_MSG: path.append(1); body_text = fetchPart(mail,path,true); target_body.setBodytext(body_text); target_body.setDescription(singlePart); break; case MAILIMAP_BODY_TYPE_1PART_TEXT: qDebug("Mediatype single: %s",mailDescription->bd_data.bd_type_text->bd_media_text); path.append(1); body_text = fetchPart(mail,path,true); target_body.setBodytext(body_text); target_body.setDescription(singlePart); break; case MAILIMAP_BODY_TYPE_1PART_BASIC: qDebug("Single attachment"); target_body.setBodytext(""); target_body.addPart(singlePart); break; default: break; } return; } QStringList IMAPwrapper::address_list_to_stringlist(clist*list) { QStringList l; QString from; bool named_from; clistcell *current = NULL; mailimap_address * current_address=NULL; if (!list) { return l; } unsigned int count = 0; for (current=clist_begin(list);current!= NULL;current=clist_next(current)) { from = ""; named_from = false; current_address=(mailimap_address*)current->data; if (current_address->ad_personal_name){ from+=QString(current_address->ad_personal_name); from+=" "; named_from = true; } if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) { from+="<"; } if (current_address->ad_mailbox_name) { from+=QString(current_address->ad_mailbox_name); from+="@"; } if (current_address->ad_host_name) { from+=QString(current_address->ad_host_name); } if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) { from+=">"; } l.append(QString(from)); if (++count > 99) { break; } } return l; } QString IMAPwrapper::fetchPart(const RecMail&mail,const QValueList<int>&path,bool internal_call) { QString body(""); const char*mb; int err; mailimap_fetch_type *fetchType; mailimap_set *set; clistcell*current,*cur; login(); if (!m_imap) { return body; } if (!internal_call) { mb = mail.getMbox().latin1(); err = mailimap_select( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox: %s",m_imap->imap_response); return body; } } set = mailimap_set_new_single(mail.getNumber()); clist*id_list=clist_new(); for (unsigned j=0; j < path.count();++j) { uint32_t * p_id = (uint32_t *)malloc(sizeof(*p_id)); *p_id = path[j]; clist_append(id_list,p_id); } mailimap_section_part * section_part = mailimap_section_part_new(id_list); mailimap_section_spec * section_spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, NULL, section_part, NULL); mailimap_section * section = mailimap_section_new(section_spec); mailimap_fetch_att * fetch_att = mailimap_fetch_att_new_body_section(section); fetchType = mailimap_fetch_type_new_fetch_att(fetch_att); clist*result = clist_new(); err = mailimap_fetch( m_imap, set, fetchType, &result ); mailimap_set_free( set ); mailimap_fetch_type_free( fetchType ); if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) { mailimap_msg_att * msg_att; msg_att = (mailimap_msg_att*)current->data; mailimap_msg_att_item*msg_att_item; for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) { msg_att_item = (mailimap_msg_att_item*)clist_content(cur); if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { if (msg_att_item->att_data.att_static->att_type == MAILIMAP_MSG_ATT_BODY_SECTION) { char*text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = 0L; if (text) { body = QString(text); free(text); } else { body = ""; } } } } } else { qDebug("error fetching text: %s",m_imap->imap_response); } mailimap_fetch_list_free(result); return body; } void IMAPwrapper::searchBodyText(const RecMail&mail,mailimap_body_type_mpart*mailDescription,RecBody&target_body,int current_recursion,QValueList<int>recList) { /* current_recursion is for avoiding ugly mails which has a to deep body-structure */ if (!mailDescription||current_recursion==10) { return; } clistcell*current; mailimap_body*current_body; unsigned int count = 0; for (current=clist_begin(mailDescription->bd_list);current!=0;current=clist_next(current)) { /* the point in the message */ ++count; current_body = (mailimap_body*)current->data; if (current_body->bd_type==MAILIMAP_BODY_MPART) { QValueList<int>clist = recList; clist.append(count); searchBodyText(mail,current_body->bd_data.bd_body_mpart,target_body,current_recursion+1,clist); } else if (current_body->bd_type==MAILIMAP_BODY_1PART){ RecPart currentPart; fillSinglePart(currentPart,current_body->bd_data.bd_body_1part); QValueList<int>clist = recList; clist.append(count); /* important: Check for is NULL 'cause a body can be empty! */ if (currentPart.Type()=="text" && target_body.Bodytext().isNull() ) { QString body_text = fetchPart(mail,clist,true); target_body.setDescription(currentPart); target_body.setBodytext(body_text); } else { QString id(""); for (unsigned int j = 0; j < clist.count();++j) { id+=(j>0?" ":""); id+=QString("%1").arg(clist[j]); } qDebug("ID= %s",id.latin1()); currentPart.setIdentifier(id); currentPart.setPositionlist(clist); target_body.addPart(currentPart); } } } } void IMAPwrapper::fillSinglePart(RecPart&target_part,mailimap_body_type_1part*Description) { if (!Description) { return; } switch (Description->bd_type) { case MAILIMAP_BODY_TYPE_1PART_TEXT: target_part.setType("text"); fillSingleTextPart(target_part,Description->bd_data.bd_type_text); break; case MAILIMAP_BODY_TYPE_1PART_BASIC: fillSingleBasicPart(target_part,Description->bd_data.bd_type_basic); break; case MAILIMAP_BODY_TYPE_1PART_MSG: fillSingleMsgPart(target_part,Description->bd_data.bd_type_msg); break; default: break; } } void IMAPwrapper::fillSingleTextPart(RecPart&target_part,mailimap_body_type_text*which) { if (!which) { return; } QString sub; sub = which->bd_media_text; target_part.setSubtype(sub.lower()); target_part.setLines(which->bd_lines); fillBodyFields(target_part,which->bd_fields); } void IMAPwrapper::fillSingleMsgPart(RecPart&target_part,mailimap_body_type_msg*which) { if (!which) { return; } // QString sub; // sub = which->bd_media_text; // target_part.setSubtype(sub.lower()); qDebug("Message part"); /* we set this type to text/plain */ target_part.setType("text"); target_part.setSubtype("plain"); target_part.setLines(which->bd_lines); fillBodyFields(target_part,which->bd_fields); } void IMAPwrapper::fillSingleBasicPart(RecPart&target_part,mailimap_body_type_basic*which) { if (!which) { return; } QString type,sub; switch (which->bd_media_basic->med_type) { case MAILIMAP_MEDIA_BASIC_APPLICATION: type = "application"; break; case MAILIMAP_MEDIA_BASIC_AUDIO: type = "audio"; break; case MAILIMAP_MEDIA_BASIC_IMAGE: type = "image"; break; case MAILIMAP_MEDIA_BASIC_MESSAGE: type = "message"; break; case MAILIMAP_MEDIA_BASIC_VIDEO: type = "video"; break; case MAILIMAP_MEDIA_BASIC_OTHER: default: if (which->bd_media_basic->med_basic_type) { type = which->bd_media_basic->med_basic_type; } else { type = ""; } break; } if (which->bd_media_basic->med_subtype) { sub = which->bd_media_basic->med_subtype; } else { sub = ""; } qDebug("Type = %s/%s",type.latin1(),sub.latin1()); target_part.setType(type.lower()); target_part.setSubtype(sub.lower()); fillBodyFields(target_part,which->bd_fields); } void IMAPwrapper::fillBodyFields(RecPart&target_part,mailimap_body_fields*which) { if (!which) return; if (which->bd_parameter && which->bd_parameter->pa_list && which->bd_parameter->pa_list->count>0) { clistcell*cur; mailimap_single_body_fld_param*param=0; for (cur = clist_begin(which->bd_parameter->pa_list);cur!=NULL;cur=clist_next(cur)) { param = (mailimap_single_body_fld_param*)cur->data; if (param) { target_part.addParameter(QString(param->pa_name).lower(),QString(param->pa_value)); } } } mailimap_body_fld_enc*enc = which->bd_encoding; QString encoding(""); switch (enc->enc_type) { case MAILIMAP_BODY_FLD_ENC_7BIT: encoding = "7bit"; break; case MAILIMAP_BODY_FLD_ENC_8BIT: encoding = "8bit"; break; case MAILIMAP_BODY_FLD_ENC_BINARY: encoding="binary"; break; case MAILIMAP_BODY_FLD_ENC_BASE64: encoding="base64"; break; case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: encoding="quoted-printable"; break; case MAILIMAP_BODY_FLD_ENC_OTHER: default: if (enc->enc_value) { char*t=enc->enc_value; encoding=QString(enc->enc_value); enc->enc_value=0L; free(t); } } target_part.setEncoding(encoding); target_part.setSize(which->bd_size); } QString IMAPwrapper::fetchPart(const RecMail&mail,const RecPart&part) { return fetchPart(mail,part.Positionlist(),false); } void IMAPwrapper::deleteMail(const RecMail&mail) { mailimap_flag_list*flist; mailimap_set *set; mailimap_store_att_flags * store_flags; int err; login(); if (!m_imap) { return; } const char *mb = mail.getMbox().latin1(); err = mailimap_select( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox for delete: %s",m_imap->imap_response); return; } flist = mailimap_flag_list_new_empty(); mailimap_flag_list_add(flist,mailimap_flag_new_deleted()); store_flags = mailimap_store_att_flags_new_set_flags(flist); set = mailimap_set_new_single(mail.getNumber()); err = mailimap_store(m_imap,set,store_flags); mailimap_set_free( set ); mailimap_store_att_flags_free(store_flags); if (err != MAILIMAP_NO_ERROR) { qDebug("error deleting mail: %s",m_imap->imap_response); return; } qDebug("deleting mail: %s",m_imap->imap_response); /* should we realy do that at this moment? */ err = mailimap_expunge(m_imap); if (err != MAILIMAP_NO_ERROR) { qDebug("error deleting mail: %s",m_imap->imap_response); } qDebug("Delete successfull %s",m_imap->imap_response); } void IMAPwrapper::answeredMail(const RecMail&mail) { mailimap_flag_list*flist; mailimap_set *set; mailimap_store_att_flags * store_flags; int err; login(); if (!m_imap) { return; } const char *mb = mail.getMbox().latin1(); err = mailimap_select( m_imap, (char*)mb); if ( err != MAILIMAP_NO_ERROR ) { qDebug("error selecting mailbox for mark: %s",m_imap->imap_response); return; } flist = mailimap_flag_list_new_empty(); mailimap_flag_list_add(flist,mailimap_flag_new_answered()); store_flags = mailimap_store_att_flags_new_set_flags(flist); set = mailimap_set_new_single(mail.getNumber()); err = mailimap_store(m_imap,set,store_flags); mailimap_set_free( set ); mailimap_store_att_flags_free(store_flags); if (err != MAILIMAP_NO_ERROR) { qDebug("error marking mail: %s",m_imap->imap_response); return; } } diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.cpp b/noncore/net/mail/libmailwrapper/mailwrapper.cpp index 3ffc274..96602c2 100644 --- a/noncore/net/mail/libmailwrapper/mailwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/mailwrapper.cpp @@ -1,629 +1,639 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <qdir.h> #include "mailwrapper.h" #include "logindialog.h" //#include "mail.h" #include "defines.h" Attachment::Attachment( DocLnk lnk ) { doc = lnk; size = QFileInfo( doc.file() ).size(); } Folder::Folder(const QString&tmp_name ) { name = tmp_name; nameDisplay = name; for ( int pos = nameDisplay.find( '&' ); pos != -1; pos = nameDisplay.find( '&' ) ) { int end = nameDisplay.find( '-' ); if ( end == -1 || end <= pos ) break; QString str64 = nameDisplay.mid( pos + 1, end - pos - 1 ); // TODO: do real base64 decoding here ! if ( str64.compare( "APw" ) == 0 ) { nameDisplay = nameDisplay.replace( pos, end - pos + 1, "ue" ); } else if ( str64.compare( "APY" ) == 0 ) { nameDisplay = nameDisplay.replace( pos, end - pos + 1, "oe" ); } } - qDebug( "folder " + name + " - displayed as " + nameDisplay ); } + +IMAPFolder::IMAPFolder(const QString&name,bool select,const QString&prefix ) + : Folder( name ),m_MaySelect(select) +{ + if (prefix.length()>0) { + if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) { + nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length()); + } + } +} + MailWrapper::MailWrapper( Settings *s ) : QObject() { settings = s; } QString MailWrapper::mailsmtpError( int errnum ) { switch ( errnum ) { case MAILSMTP_NO_ERROR: return tr( "No error" ); case MAILSMTP_ERROR_UNEXPECTED_CODE: return tr( "Unexpected error code" ); case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: return tr( "Service not available" ); case MAILSMTP_ERROR_STREAM: return tr( "Stream error" ); case MAILSMTP_ERROR_HOSTNAME: return tr( "gethostname() failed" ); case MAILSMTP_ERROR_NOT_IMPLEMENTED: return tr( "Not implemented" ); case MAILSMTP_ERROR_ACTION_NOT_TAKEN: return tr( "Error, action not taken" ); case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: return tr( "Data exceeds storage allocation" ); case MAILSMTP_ERROR_IN_PROCESSING: return tr( "Error in processing" ); // case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE: // return tr( "Insufficient system storage" ); case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: return tr( "Mailbox unavailable" ); case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: return tr( "Mailbox name not allowed" ); case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: return tr( "Bad command sequence" ); case MAILSMTP_ERROR_USER_NOT_LOCAL: return tr( "User not local" ); case MAILSMTP_ERROR_TRANSACTION_FAILED: return tr( "Transaction failed" ); case MAILSMTP_ERROR_MEMORY: return tr( "Memory error" ); case MAILSMTP_ERROR_CONNECTION_REFUSED: return tr( "Connection refused" ); default: return tr( "Unknown error code" ); } } mailimf_mailbox *MailWrapper::newMailbox(const QString&name, const QString&mail ) { return mailimf_mailbox_new( strdup( name.latin1() ), strdup( mail.latin1() ) ); } mailimf_address_list *MailWrapper::parseAddresses(const QString&addr ) { mailimf_address_list *addresses; if ( addr.isEmpty() ) return NULL; addresses = mailimf_address_list_new_empty(); QStringList list = QStringList::split( ',', addr ); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); it++ ) { char *str = strdup( (*it).latin1() ); int err = mailimf_address_list_add_parse( addresses, str ); if ( err != MAILIMF_NO_ERROR ) { qDebug( "Error parsing" ); qDebug( *it ); free( str ); } else { qDebug( "Parse success! :)" ); } } return addresses; } mailimf_fields *MailWrapper::createImfFields( Mail *mail ) { mailimf_fields *fields; mailimf_field *xmailer; mailimf_mailbox *sender, *fromBox; mailimf_mailbox_list *from; mailimf_address_list *to, *cc, *bcc, *reply; char *subject = strdup( mail->getSubject().latin1() ); int err; sender = newMailbox( mail->getName(), mail->getMail() ); if ( sender == NULL ) goto err_free; fromBox = newMailbox( mail->getName(), mail->getMail() ); if ( fromBox == NULL ) goto err_free_sender; from = mailimf_mailbox_list_new_empty(); if ( from == NULL ) goto err_free_fromBox; err = mailimf_mailbox_list_add( from, fromBox ); if ( err != MAILIMF_NO_ERROR ) goto err_free_from; to = parseAddresses( mail->getTo() ); if ( to == NULL ) goto err_free_from; cc = parseAddresses( mail->getCC() ); bcc = parseAddresses( mail->getBCC() ); reply = parseAddresses( mail->getReply() ); fields = mailimf_fields_new_with_data( from, sender, reply, to, cc, bcc, NULL, NULL, subject ); if ( fields == NULL ) goto err_free_reply; xmailer = mailimf_field_new_custom( strdup( "User-Agent" ), strdup( USER_AGENT ) ); if ( xmailer == NULL ) goto err_free_fields; err = mailimf_fields_add( fields, xmailer ); if ( err != MAILIMF_NO_ERROR ) goto err_free_xmailer; return fields; // Success :) err_free_xmailer: mailimf_field_free( xmailer ); err_free_fields: mailimf_fields_free( fields ); err_free_reply: mailimf_address_list_free( reply ); mailimf_address_list_free( bcc ); mailimf_address_list_free( cc ); mailimf_address_list_free( to ); err_free_from: mailimf_mailbox_list_free( from ); err_free_fromBox: mailimf_mailbox_free( fromBox ); err_free_sender: mailimf_mailbox_free( sender ); err_free: free( subject ); qDebug( "createImfFields - error" ); return NULL; // Error :( } mailmime *MailWrapper::buildTxtPart( QString str ) { mailmime *txtPart; mailmime_fields *fields; mailmime_content *content; mailmime_parameter *param; char *txt = strdup( str.latin1() ); int err; param = mailmime_parameter_new( strdup( "charset" ), strdup( "iso-8859-1" ) ); if ( param == NULL ) goto err_free; content = mailmime_content_new_with_str( "text/plain" ); if ( content == NULL ) goto err_free_param; err = clist_append( content->ct_parameters, param ); if ( err != MAILIMF_NO_ERROR ) goto err_free_content; fields = mailmime_fields_new_encoding( MAILMIME_MECHANISM_8BIT ); if ( fields == NULL ) goto err_free_content; txtPart = mailmime_new_empty( content, fields ); if ( txtPart == NULL ) goto err_free_fields; err = mailmime_set_body_text( txtPart, txt, strlen( txt ) ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; return txtPart; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_fields: mailmime_fields_free( fields ); err_free_content: mailmime_content_free( content ); err_free_param: mailmime_parameter_free( param ); err_free: free( txt ); qDebug( "buildTxtPart - error" ); return NULL; // Error :( } mailmime *MailWrapper::buildFilePart( QString filename, QString mimetype ) { mailmime * filePart; mailmime_fields * fields; mailmime_content * content; mailmime_parameter * param = NULL; int err; int pos = filename.findRev( '/' ); QString tmp = filename.right( filename.length() - ( pos + 1 ) ); char *name = strdup( tmp.latin1() ); // just filename char *file = strdup( filename.latin1() ); // full name with path char *mime = strdup( mimetype.latin1() ); // mimetype -e.g. text/plain fields = mailmime_fields_new_filename( MAILMIME_DISPOSITION_TYPE_ATTACHMENT, name, MAILMIME_MECHANISM_BASE64 ); if ( fields == NULL ) goto err_free; content = mailmime_content_new_with_str( mime ); if ( content == NULL ) goto err_free_fields; if ( mimetype.compare( "text/plain" ) == 0 ) { param = mailmime_parameter_new( strdup( "charset" ), strdup( "iso-8859-1" ) ); if ( param == NULL ) goto err_free_content; err = clist_append( content->ct_parameters, param ); if ( err != MAILIMF_NO_ERROR ) goto err_free_param; } filePart = mailmime_new_empty( content, fields ); if ( filePart == NULL ) goto err_free_param; err = mailmime_set_body_file( filePart, file ); if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart; return filePart; // Success :) err_free_filePart: mailmime_free( filePart ); err_free_param: if ( param != NULL ) mailmime_parameter_free( param ); err_free_content: mailmime_content_free( content ); err_free_fields: mailmime_fields_free( fields ); err_free: free( name ); free( mime ); free( file ); qDebug( "buildFilePart - error" ); return NULL; // Error :( } void MailWrapper::addFileParts( mailmime *message, QList<Attachment> files ) { Attachment *it; for ( it = files.first(); it; it = files.next() ) { qDebug( "Adding file" ); mailmime *filePart; int err; filePart = buildFilePart( it->getFileName(), it->getMimeType() ); if ( filePart == NULL ) goto err_free; err = mailmime_smart_add_part( message, filePart ); if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart; continue; // Success :) err_free_filePart: mailmime_free( filePart ); err_free: qDebug( "addFileParts: error adding file:" ); qDebug( it->getFileName() ); } } mailmime *MailWrapper::createMimeMail( Mail *mail ) { mailmime *message, *txtPart; mailimf_fields *fields; int err; fields = createImfFields( mail ); if ( fields == NULL ) goto err_free; message = mailmime_new_message_data( NULL ); if ( message == NULL ) goto err_free_fields; mailmime_set_imf_fields( message, fields ); txtPart = buildTxtPart( mail->getMessage() ); if ( txtPart == NULL ) goto err_free_message; err = mailmime_smart_add_part( message, txtPart ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; addFileParts( message, mail->getAttachments() ); return message; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_message: mailmime_free( message ); err_free_fields: mailimf_fields_free( fields ); err_free: qDebug( "createMimeMail: error" ); return NULL; // Error :( } mailimf_field *MailWrapper::getField( mailimf_fields *fields, int type ) { mailimf_field *field; clistiter *it; it = clist_begin( fields->fld_list ); while ( it ) { field = (mailimf_field *) it->data; if ( field->fld_type == type ) { return field; } it = it->next; } return NULL; } static void addRcpts( clist *list, mailimf_address_list *addr_list ) { clistiter *it, *it2; for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) { mailimf_address *addr; addr = (mailimf_address *) it->data; if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) { esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL ); } else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) { clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list; for ( it2 = clist_begin( l ); it2; it2 = it2->next ) { mailimf_mailbox *mbox; mbox = (mailimf_mailbox *) it2->data; esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL ); } } } } clist *MailWrapper::createRcptList( mailimf_fields *fields ) { clist *rcptList; mailimf_field *field; rcptList = esmtp_address_list_new(); field = getField( fields, MAILIMF_FIELD_TO ); if ( field && (field->fld_type == MAILIMF_FIELD_TO) && field->fld_data.fld_to->to_addr_list ) { addRcpts( rcptList, field->fld_data.fld_to->to_addr_list ); } field = getField( fields, MAILIMF_FIELD_CC ); if ( field && (field->fld_type == MAILIMF_FIELD_CC) && field->fld_data.fld_cc->cc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list ); } field = getField( fields, MAILIMF_FIELD_BCC ); if ( field && (field->fld_type == MAILIMF_FIELD_BCC) && field->fld_data.fld_bcc->bcc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list ); } return rcptList; } char *MailWrapper::getFrom( mailmime *mail ) { char *from = NULL; mailimf_field *ffrom; ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM ); if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM) && ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) { clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list; clistiter *it; for ( it = clist_begin( cl ); it; it = it->next ) { mailimf_mailbox *mb = (mailimf_mailbox *) it->data; from = strdup( mb->mb_addr_spec ); } } return from; } SMTPaccount *MailWrapper::getAccount( QString from ) { SMTPaccount *smtp; QList<Account> list = settings->getAccounts(); Account *it; for ( it = list.first(); it; it = list.next() ) { if ( it->getType().compare( "SMTP" ) == 0 ) { smtp = static_cast<SMTPaccount *>(it); if ( smtp->getMail().compare( from ) == 0 ) { qDebug( "SMTPaccount found for" ); qDebug( from ); return smtp; } } } return NULL; } QString MailWrapper::getTmpFile() { int num = 0; QString unique; QDir dir( "/tmp" ); QStringList::Iterator it; QStringList list = dir.entryList( "opiemail-tmp-*" ); do { unique.setNum( num++ ); } while ( list.contains( "opiemail-tmp-" + unique ) > 0 ); return "/tmp/opiemail-tmp-" + unique; } void MailWrapper::writeToFile( QString file, mailmime *mail ) { FILE *f; int err, col = 0; f = fopen( file.latin1(), "w" ); if ( f == NULL ) { qDebug( "writeToFile: error opening file" ); return; } err = mailmime_write( f, &col, mail ); if ( err != MAILIMF_NO_ERROR ) { fclose( f ); qDebug( "writeToFile: error writing mailmime" ); return; } fclose( f ); } void MailWrapper::readFromFile( QString file, char **data, size_t *size ) { char *buf; struct stat st; int fd, count = 0, total = 0; fd = open( file.latin1(), O_RDONLY, 0 ); if ( fd == -1 ) return; if ( fstat( fd, &st ) != 0 ) goto err_close; if ( !st.st_size ) goto err_close; buf = (char *) malloc( st.st_size ); if ( !buf ) goto err_close; while ( ( total < st.st_size ) && ( count >= 0 ) ) { count = read( fd, buf + total, st.st_size - total ); total += count; } if ( count < 0 ) goto err_free; *data = buf; *size = st.st_size; close( fd ); return; // Success :) err_free: free( buf ); err_close: close( fd ); } void progress( size_t current, size_t maximum ) { qDebug( "Current: %i of %i", current, maximum ); } void MailWrapper::smtpSend( mailmime *mail ) { mailsmtp *session; clist *rcpts; char *from, *data, *server, *user = NULL, *pass = NULL; size_t size; int err; bool ssl; uint16_t port; from = getFrom( mail ); SMTPaccount *smtp = getAccount( from ); if ( smtp == NULL ) { free(from); return; } server = strdup( smtp->getServer().latin1() ); ssl = smtp->getSSL(); port = smtp->getPort().toUInt(); rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); QString file = getTmpFile(); writeToFile( file, mail ); readFromFile( file, &data, &size ); QFile f( file ); f.remove(); session = mailsmtp_new( 20, &progress ); if ( session == NULL ) goto free_mem; qDebug( "Servername %s at port %i", server, port ); if ( ssl ) { qDebug( "SSL session" ); err = mailsmtp_ssl_connect( session, server, port ); } else { qDebug( "No SSL session" ); err = mailsmtp_socket_connect( session, server, port ); } if ( err != MAILSMTP_NO_ERROR ) goto free_mem_session; err = mailsmtp_init( session ); if ( err != MAILSMTP_NO_ERROR ) goto free_con_session; qDebug( "INIT OK" ); if ( smtp->getLogin() ) { if ( smtp->getUser().isEmpty() || smtp->getPassword().isEmpty() ) { // get'em LoginDialog login( smtp->getUser(), smtp->getPassword(), NULL, 0, true ); login.show(); if ( QDialog::Accepted == login.exec() ) { // ok user = strdup( login.getUser().latin1() ); pass = strdup( login.getPassword().latin1() ); } else { goto free_con_session; } } else { user = strdup( smtp->getUser().latin1() ); pass = strdup( smtp->getPassword().latin1() ); } qDebug( "session->auth: %i", session->auth); err = mailsmtp_auth( session, user, pass ); if ( err == MAILSMTP_NO_ERROR ) qDebug("auth ok"); qDebug( "Done auth!" ); } err = mailsmtp_send( session, from, rcpts, data, size ); if ( err != MAILSMTP_NO_ERROR ) goto free_con_session; qDebug( "Mail sent." ); free_con_session: mailsmtp_quit( session ); free_mem_session: mailsmtp_free( session ); free_mem: smtp_address_list_free( rcpts ); free( data ); free( server ); if ( smtp->getLogin() ) { free( user ); free( pass ); } free( from ); } void MailWrapper::sendMail( Mail mail ) { mailmime *mimeMail; mimeMail = createMimeMail( &mail ); if ( mimeMail == NULL ) { qDebug( "sendMail: error creating mime mail" ); } else { smtpSend( mimeMail ); mailmime_free( mimeMail ); } } Mail::Mail() :name(""), mail(""), to(""), cc(""), bcc(""), reply(""), subject(""), message("") { } diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.h b/noncore/net/mail/libmailwrapper/mailwrapper.h index 34fd5c5..6994dd8 100644 --- a/noncore/net/mail/libmailwrapper/mailwrapper.h +++ b/noncore/net/mail/libmailwrapper/mailwrapper.h @@ -1,123 +1,123 @@ #ifndef MAILWRAPPER_H #define MAILWRAPPER_H #include <qpe/applnk.h> #include <libetpan/mailmime.h> #include <libetpan/mailimf.h> #include <libetpan/mailsmtp.h> #include <libetpan/mailstorage.h> #include <libetpan/maildriver.h> #include <qbitarray.h> #include <qdatetime.h> #include "settings.h" class Attachment { public: Attachment( DocLnk lnk ); virtual ~Attachment(){} const QString getFileName()const{ return doc.file(); } const QString getName()const{ return doc.name(); } const QString getMimeType()const{ return doc.type(); } const QPixmap getPixmap()const{ return doc.pixmap(); } const int getSize()const { return size; } DocLnk getDocLnk() { return doc; } protected: DocLnk doc; int size; }; class Mail { public: Mail(); /* Possible that this destructor must not be declared virtual * 'cause it seems that it will never have some child classes. * in this case this object will not get a virtual table -> memory and * speed will be a little bit better? */ virtual ~Mail(){} void addAttachment( Attachment *att ) { attList.append( att ); } const QList<Attachment>& getAttachments()const { return attList; } void removeAttachment( Attachment *att ) { attList.remove( att ); } const QString&getName()const { return name; } void setName( QString s ) { name = s; } const QString&getMail()const{ return mail; } void setMail( const QString&s ) { mail = s; } const QString&getTo()const{ return to; } void setTo( const QString&s ) { to = s; } const QString&getCC()const{ return cc; } void setCC( const QString&s ) { cc = s; } const QString&getBCC()const { return bcc; } void setBCC( const QString&s ) { bcc = s; } const QString&getMessage()const { return message; } void setMessage( const QString&s ) { message = s; } const QString&getSubject()const { return subject; } void setSubject( const QString&s ) { subject = s; } const QString&getReply()const{ return reply; } void setReply( const QString&a ) { reply = a; } private: QList<Attachment> attList; QString name, mail, to, cc, bcc, reply, subject, message; }; class Folder : public QObject { Q_OBJECT public: Folder( const QString&init_name ); const QString&getDisplayName()const { return nameDisplay; } const QString&getName()const { return name; } virtual bool may_select()const{return true;}; -private: +protected: QString nameDisplay, name; }; class IMAPFolder : public Folder { public: - IMAPFolder( QString name,bool select=true ) : Folder( name ),m_MaySelect(select) {} + IMAPFolder(const QString&name,bool select=true,const QString&prefix="" ); virtual bool may_select()const{return m_MaySelect;} private: bool m_MaySelect; }; class MailWrapper : public QObject { Q_OBJECT public: MailWrapper( Settings *s ); void sendMail( Mail mail ); private: mailimf_mailbox *newMailbox(const QString&name,const QString&mail ); mailimf_address_list *parseAddresses(const QString&addr ); mailimf_fields *createImfFields( Mail *mail ); mailmime *buildTxtPart( QString str ); mailmime *buildFilePart( QString filename, QString mimetype ); void addFileParts( mailmime *message, QList<Attachment> files ); mailmime *createMimeMail( Mail *mail ); void smtpSend( mailmime *mail ); mailimf_field *getField( mailimf_fields *fields, int type ); clist *createRcptList( mailimf_fields *fields ); char *getFrom( mailmime *mail ); SMTPaccount *getAccount( QString from ); void writeToFile( QString file, mailmime *mail ); void readFromFile( QString file, char **data, size_t *size ); static QString mailsmtpError( int err ); static QString getTmpFile(); Settings *settings; }; #endif diff --git a/noncore/net/mail/mailwrapper.cpp b/noncore/net/mail/mailwrapper.cpp index 3ffc274..96602c2 100644 --- a/noncore/net/mail/mailwrapper.cpp +++ b/noncore/net/mail/mailwrapper.cpp @@ -1,629 +1,639 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <qdir.h> #include "mailwrapper.h" #include "logindialog.h" //#include "mail.h" #include "defines.h" Attachment::Attachment( DocLnk lnk ) { doc = lnk; size = QFileInfo( doc.file() ).size(); } Folder::Folder(const QString&tmp_name ) { name = tmp_name; nameDisplay = name; for ( int pos = nameDisplay.find( '&' ); pos != -1; pos = nameDisplay.find( '&' ) ) { int end = nameDisplay.find( '-' ); if ( end == -1 || end <= pos ) break; QString str64 = nameDisplay.mid( pos + 1, end - pos - 1 ); // TODO: do real base64 decoding here ! if ( str64.compare( "APw" ) == 0 ) { nameDisplay = nameDisplay.replace( pos, end - pos + 1, "ue" ); } else if ( str64.compare( "APY" ) == 0 ) { nameDisplay = nameDisplay.replace( pos, end - pos + 1, "oe" ); } } - qDebug( "folder " + name + " - displayed as " + nameDisplay ); } + +IMAPFolder::IMAPFolder(const QString&name,bool select,const QString&prefix ) + : Folder( name ),m_MaySelect(select) +{ + if (prefix.length()>0) { + if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) { + nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length()); + } + } +} + MailWrapper::MailWrapper( Settings *s ) : QObject() { settings = s; } QString MailWrapper::mailsmtpError( int errnum ) { switch ( errnum ) { case MAILSMTP_NO_ERROR: return tr( "No error" ); case MAILSMTP_ERROR_UNEXPECTED_CODE: return tr( "Unexpected error code" ); case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: return tr( "Service not available" ); case MAILSMTP_ERROR_STREAM: return tr( "Stream error" ); case MAILSMTP_ERROR_HOSTNAME: return tr( "gethostname() failed" ); case MAILSMTP_ERROR_NOT_IMPLEMENTED: return tr( "Not implemented" ); case MAILSMTP_ERROR_ACTION_NOT_TAKEN: return tr( "Error, action not taken" ); case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: return tr( "Data exceeds storage allocation" ); case MAILSMTP_ERROR_IN_PROCESSING: return tr( "Error in processing" ); // case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE: // return tr( "Insufficient system storage" ); case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: return tr( "Mailbox unavailable" ); case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: return tr( "Mailbox name not allowed" ); case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: return tr( "Bad command sequence" ); case MAILSMTP_ERROR_USER_NOT_LOCAL: return tr( "User not local" ); case MAILSMTP_ERROR_TRANSACTION_FAILED: return tr( "Transaction failed" ); case MAILSMTP_ERROR_MEMORY: return tr( "Memory error" ); case MAILSMTP_ERROR_CONNECTION_REFUSED: return tr( "Connection refused" ); default: return tr( "Unknown error code" ); } } mailimf_mailbox *MailWrapper::newMailbox(const QString&name, const QString&mail ) { return mailimf_mailbox_new( strdup( name.latin1() ), strdup( mail.latin1() ) ); } mailimf_address_list *MailWrapper::parseAddresses(const QString&addr ) { mailimf_address_list *addresses; if ( addr.isEmpty() ) return NULL; addresses = mailimf_address_list_new_empty(); QStringList list = QStringList::split( ',', addr ); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); it++ ) { char *str = strdup( (*it).latin1() ); int err = mailimf_address_list_add_parse( addresses, str ); if ( err != MAILIMF_NO_ERROR ) { qDebug( "Error parsing" ); qDebug( *it ); free( str ); } else { qDebug( "Parse success! :)" ); } } return addresses; } mailimf_fields *MailWrapper::createImfFields( Mail *mail ) { mailimf_fields *fields; mailimf_field *xmailer; mailimf_mailbox *sender, *fromBox; mailimf_mailbox_list *from; mailimf_address_list *to, *cc, *bcc, *reply; char *subject = strdup( mail->getSubject().latin1() ); int err; sender = newMailbox( mail->getName(), mail->getMail() ); if ( sender == NULL ) goto err_free; fromBox = newMailbox( mail->getName(), mail->getMail() ); if ( fromBox == NULL ) goto err_free_sender; from = mailimf_mailbox_list_new_empty(); if ( from == NULL ) goto err_free_fromBox; err = mailimf_mailbox_list_add( from, fromBox ); if ( err != MAILIMF_NO_ERROR ) goto err_free_from; to = parseAddresses( mail->getTo() ); if ( to == NULL ) goto err_free_from; cc = parseAddresses( mail->getCC() ); bcc = parseAddresses( mail->getBCC() ); reply = parseAddresses( mail->getReply() ); fields = mailimf_fields_new_with_data( from, sender, reply, to, cc, bcc, NULL, NULL, subject ); if ( fields == NULL ) goto err_free_reply; xmailer = mailimf_field_new_custom( strdup( "User-Agent" ), strdup( USER_AGENT ) ); if ( xmailer == NULL ) goto err_free_fields; err = mailimf_fields_add( fields, xmailer ); if ( err != MAILIMF_NO_ERROR ) goto err_free_xmailer; return fields; // Success :) err_free_xmailer: mailimf_field_free( xmailer ); err_free_fields: mailimf_fields_free( fields ); err_free_reply: mailimf_address_list_free( reply ); mailimf_address_list_free( bcc ); mailimf_address_list_free( cc ); mailimf_address_list_free( to ); err_free_from: mailimf_mailbox_list_free( from ); err_free_fromBox: mailimf_mailbox_free( fromBox ); err_free_sender: mailimf_mailbox_free( sender ); err_free: free( subject ); qDebug( "createImfFields - error" ); return NULL; // Error :( } mailmime *MailWrapper::buildTxtPart( QString str ) { mailmime *txtPart; mailmime_fields *fields; mailmime_content *content; mailmime_parameter *param; char *txt = strdup( str.latin1() ); int err; param = mailmime_parameter_new( strdup( "charset" ), strdup( "iso-8859-1" ) ); if ( param == NULL ) goto err_free; content = mailmime_content_new_with_str( "text/plain" ); if ( content == NULL ) goto err_free_param; err = clist_append( content->ct_parameters, param ); if ( err != MAILIMF_NO_ERROR ) goto err_free_content; fields = mailmime_fields_new_encoding( MAILMIME_MECHANISM_8BIT ); if ( fields == NULL ) goto err_free_content; txtPart = mailmime_new_empty( content, fields ); if ( txtPart == NULL ) goto err_free_fields; err = mailmime_set_body_text( txtPart, txt, strlen( txt ) ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; return txtPart; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_fields: mailmime_fields_free( fields ); err_free_content: mailmime_content_free( content ); err_free_param: mailmime_parameter_free( param ); err_free: free( txt ); qDebug( "buildTxtPart - error" ); return NULL; // Error :( } mailmime *MailWrapper::buildFilePart( QString filename, QString mimetype ) { mailmime * filePart; mailmime_fields * fields; mailmime_content * content; mailmime_parameter * param = NULL; int err; int pos = filename.findRev( '/' ); QString tmp = filename.right( filename.length() - ( pos + 1 ) ); char *name = strdup( tmp.latin1() ); // just filename char *file = strdup( filename.latin1() ); // full name with path char *mime = strdup( mimetype.latin1() ); // mimetype -e.g. text/plain fields = mailmime_fields_new_filename( MAILMIME_DISPOSITION_TYPE_ATTACHMENT, name, MAILMIME_MECHANISM_BASE64 ); if ( fields == NULL ) goto err_free; content = mailmime_content_new_with_str( mime ); if ( content == NULL ) goto err_free_fields; if ( mimetype.compare( "text/plain" ) == 0 ) { param = mailmime_parameter_new( strdup( "charset" ), strdup( "iso-8859-1" ) ); if ( param == NULL ) goto err_free_content; err = clist_append( content->ct_parameters, param ); if ( err != MAILIMF_NO_ERROR ) goto err_free_param; } filePart = mailmime_new_empty( content, fields ); if ( filePart == NULL ) goto err_free_param; err = mailmime_set_body_file( filePart, file ); if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart; return filePart; // Success :) err_free_filePart: mailmime_free( filePart ); err_free_param: if ( param != NULL ) mailmime_parameter_free( param ); err_free_content: mailmime_content_free( content ); err_free_fields: mailmime_fields_free( fields ); err_free: free( name ); free( mime ); free( file ); qDebug( "buildFilePart - error" ); return NULL; // Error :( } void MailWrapper::addFileParts( mailmime *message, QList<Attachment> files ) { Attachment *it; for ( it = files.first(); it; it = files.next() ) { qDebug( "Adding file" ); mailmime *filePart; int err; filePart = buildFilePart( it->getFileName(), it->getMimeType() ); if ( filePart == NULL ) goto err_free; err = mailmime_smart_add_part( message, filePart ); if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart; continue; // Success :) err_free_filePart: mailmime_free( filePart ); err_free: qDebug( "addFileParts: error adding file:" ); qDebug( it->getFileName() ); } } mailmime *MailWrapper::createMimeMail( Mail *mail ) { mailmime *message, *txtPart; mailimf_fields *fields; int err; fields = createImfFields( mail ); if ( fields == NULL ) goto err_free; message = mailmime_new_message_data( NULL ); if ( message == NULL ) goto err_free_fields; mailmime_set_imf_fields( message, fields ); txtPart = buildTxtPart( mail->getMessage() ); if ( txtPart == NULL ) goto err_free_message; err = mailmime_smart_add_part( message, txtPart ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; addFileParts( message, mail->getAttachments() ); return message; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_message: mailmime_free( message ); err_free_fields: mailimf_fields_free( fields ); err_free: qDebug( "createMimeMail: error" ); return NULL; // Error :( } mailimf_field *MailWrapper::getField( mailimf_fields *fields, int type ) { mailimf_field *field; clistiter *it; it = clist_begin( fields->fld_list ); while ( it ) { field = (mailimf_field *) it->data; if ( field->fld_type == type ) { return field; } it = it->next; } return NULL; } static void addRcpts( clist *list, mailimf_address_list *addr_list ) { clistiter *it, *it2; for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) { mailimf_address *addr; addr = (mailimf_address *) it->data; if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) { esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL ); } else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) { clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list; for ( it2 = clist_begin( l ); it2; it2 = it2->next ) { mailimf_mailbox *mbox; mbox = (mailimf_mailbox *) it2->data; esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL ); } } } } clist *MailWrapper::createRcptList( mailimf_fields *fields ) { clist *rcptList; mailimf_field *field; rcptList = esmtp_address_list_new(); field = getField( fields, MAILIMF_FIELD_TO ); if ( field && (field->fld_type == MAILIMF_FIELD_TO) && field->fld_data.fld_to->to_addr_list ) { addRcpts( rcptList, field->fld_data.fld_to->to_addr_list ); } field = getField( fields, MAILIMF_FIELD_CC ); if ( field && (field->fld_type == MAILIMF_FIELD_CC) && field->fld_data.fld_cc->cc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list ); } field = getField( fields, MAILIMF_FIELD_BCC ); if ( field && (field->fld_type == MAILIMF_FIELD_BCC) && field->fld_data.fld_bcc->bcc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list ); } return rcptList; } char *MailWrapper::getFrom( mailmime *mail ) { char *from = NULL; mailimf_field *ffrom; ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM ); if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM) && ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) { clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list; clistiter *it; for ( it = clist_begin( cl ); it; it = it->next ) { mailimf_mailbox *mb = (mailimf_mailbox *) it->data; from = strdup( mb->mb_addr_spec ); } } return from; } SMTPaccount *MailWrapper::getAccount( QString from ) { SMTPaccount *smtp; QList<Account> list = settings->getAccounts(); Account *it; for ( it = list.first(); it; it = list.next() ) { if ( it->getType().compare( "SMTP" ) == 0 ) { smtp = static_cast<SMTPaccount *>(it); if ( smtp->getMail().compare( from ) == 0 ) { qDebug( "SMTPaccount found for" ); qDebug( from ); return smtp; } } } return NULL; } QString MailWrapper::getTmpFile() { int num = 0; QString unique; QDir dir( "/tmp" ); QStringList::Iterator it; QStringList list = dir.entryList( "opiemail-tmp-*" ); do { unique.setNum( num++ ); } while ( list.contains( "opiemail-tmp-" + unique ) > 0 ); return "/tmp/opiemail-tmp-" + unique; } void MailWrapper::writeToFile( QString file, mailmime *mail ) { FILE *f; int err, col = 0; f = fopen( file.latin1(), "w" ); if ( f == NULL ) { qDebug( "writeToFile: error opening file" ); return; } err = mailmime_write( f, &col, mail ); if ( err != MAILIMF_NO_ERROR ) { fclose( f ); qDebug( "writeToFile: error writing mailmime" ); return; } fclose( f ); } void MailWrapper::readFromFile( QString file, char **data, size_t *size ) { char *buf; struct stat st; int fd, count = 0, total = 0; fd = open( file.latin1(), O_RDONLY, 0 ); if ( fd == -1 ) return; if ( fstat( fd, &st ) != 0 ) goto err_close; if ( !st.st_size ) goto err_close; buf = (char *) malloc( st.st_size ); if ( !buf ) goto err_close; while ( ( total < st.st_size ) && ( count >= 0 ) ) { count = read( fd, buf + total, st.st_size - total ); total += count; } if ( count < 0 ) goto err_free; *data = buf; *size = st.st_size; close( fd ); return; // Success :) err_free: free( buf ); err_close: close( fd ); } void progress( size_t current, size_t maximum ) { qDebug( "Current: %i of %i", current, maximum ); } void MailWrapper::smtpSend( mailmime *mail ) { mailsmtp *session; clist *rcpts; char *from, *data, *server, *user = NULL, *pass = NULL; size_t size; int err; bool ssl; uint16_t port; from = getFrom( mail ); SMTPaccount *smtp = getAccount( from ); if ( smtp == NULL ) { free(from); return; } server = strdup( smtp->getServer().latin1() ); ssl = smtp->getSSL(); port = smtp->getPort().toUInt(); rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); QString file = getTmpFile(); writeToFile( file, mail ); readFromFile( file, &data, &size ); QFile f( file ); f.remove(); session = mailsmtp_new( 20, &progress ); if ( session == NULL ) goto free_mem; qDebug( "Servername %s at port %i", server, port ); if ( ssl ) { qDebug( "SSL session" ); err = mailsmtp_ssl_connect( session, server, port ); } else { qDebug( "No SSL session" ); err = mailsmtp_socket_connect( session, server, port ); } if ( err != MAILSMTP_NO_ERROR ) goto free_mem_session; err = mailsmtp_init( session ); if ( err != MAILSMTP_NO_ERROR ) goto free_con_session; qDebug( "INIT OK" ); if ( smtp->getLogin() ) { if ( smtp->getUser().isEmpty() || smtp->getPassword().isEmpty() ) { // get'em LoginDialog login( smtp->getUser(), smtp->getPassword(), NULL, 0, true ); login.show(); if ( QDialog::Accepted == login.exec() ) { // ok user = strdup( login.getUser().latin1() ); pass = strdup( login.getPassword().latin1() ); } else { goto free_con_session; } } else { user = strdup( smtp->getUser().latin1() ); pass = strdup( smtp->getPassword().latin1() ); } qDebug( "session->auth: %i", session->auth); err = mailsmtp_auth( session, user, pass ); if ( err == MAILSMTP_NO_ERROR ) qDebug("auth ok"); qDebug( "Done auth!" ); } err = mailsmtp_send( session, from, rcpts, data, size ); if ( err != MAILSMTP_NO_ERROR ) goto free_con_session; qDebug( "Mail sent." ); free_con_session: mailsmtp_quit( session ); free_mem_session: mailsmtp_free( session ); free_mem: smtp_address_list_free( rcpts ); free( data ); free( server ); if ( smtp->getLogin() ) { free( user ); free( pass ); } free( from ); } void MailWrapper::sendMail( Mail mail ) { mailmime *mimeMail; mimeMail = createMimeMail( &mail ); if ( mimeMail == NULL ) { qDebug( "sendMail: error creating mime mail" ); } else { smtpSend( mimeMail ); mailmime_free( mimeMail ); } } Mail::Mail() :name(""), mail(""), to(""), cc(""), bcc(""), reply(""), subject(""), message("") { } diff --git a/noncore/net/mail/mailwrapper.h b/noncore/net/mail/mailwrapper.h index 34fd5c5..6994dd8 100644 --- a/noncore/net/mail/mailwrapper.h +++ b/noncore/net/mail/mailwrapper.h @@ -1,123 +1,123 @@ #ifndef MAILWRAPPER_H #define MAILWRAPPER_H #include <qpe/applnk.h> #include <libetpan/mailmime.h> #include <libetpan/mailimf.h> #include <libetpan/mailsmtp.h> #include <libetpan/mailstorage.h> #include <libetpan/maildriver.h> #include <qbitarray.h> #include <qdatetime.h> #include "settings.h" class Attachment { public: Attachment( DocLnk lnk ); virtual ~Attachment(){} const QString getFileName()const{ return doc.file(); } const QString getName()const{ return doc.name(); } const QString getMimeType()const{ return doc.type(); } const QPixmap getPixmap()const{ return doc.pixmap(); } const int getSize()const { return size; } DocLnk getDocLnk() { return doc; } protected: DocLnk doc; int size; }; class Mail { public: Mail(); /* Possible that this destructor must not be declared virtual * 'cause it seems that it will never have some child classes. * in this case this object will not get a virtual table -> memory and * speed will be a little bit better? */ virtual ~Mail(){} void addAttachment( Attachment *att ) { attList.append( att ); } const QList<Attachment>& getAttachments()const { return attList; } void removeAttachment( Attachment *att ) { attList.remove( att ); } const QString&getName()const { return name; } void setName( QString s ) { name = s; } const QString&getMail()const{ return mail; } void setMail( const QString&s ) { mail = s; } const QString&getTo()const{ return to; } void setTo( const QString&s ) { to = s; } const QString&getCC()const{ return cc; } void setCC( const QString&s ) { cc = s; } const QString&getBCC()const { return bcc; } void setBCC( const QString&s ) { bcc = s; } const QString&getMessage()const { return message; } void setMessage( const QString&s ) { message = s; } const QString&getSubject()const { return subject; } void setSubject( const QString&s ) { subject = s; } const QString&getReply()const{ return reply; } void setReply( const QString&a ) { reply = a; } private: QList<Attachment> attList; QString name, mail, to, cc, bcc, reply, subject, message; }; class Folder : public QObject { Q_OBJECT public: Folder( const QString&init_name ); const QString&getDisplayName()const { return nameDisplay; } const QString&getName()const { return name; } virtual bool may_select()const{return true;}; -private: +protected: QString nameDisplay, name; }; class IMAPFolder : public Folder { public: - IMAPFolder( QString name,bool select=true ) : Folder( name ),m_MaySelect(select) {} + IMAPFolder(const QString&name,bool select=true,const QString&prefix="" ); virtual bool may_select()const{return m_MaySelect;} private: bool m_MaySelect; }; class MailWrapper : public QObject { Q_OBJECT public: MailWrapper( Settings *s ); void sendMail( Mail mail ); private: mailimf_mailbox *newMailbox(const QString&name,const QString&mail ); mailimf_address_list *parseAddresses(const QString&addr ); mailimf_fields *createImfFields( Mail *mail ); mailmime *buildTxtPart( QString str ); mailmime *buildFilePart( QString filename, QString mimetype ); void addFileParts( mailmime *message, QList<Attachment> files ); mailmime *createMimeMail( Mail *mail ); void smtpSend( mailmime *mail ); mailimf_field *getField( mailimf_fields *fields, int type ); clist *createRcptList( mailimf_fields *fields ); char *getFrom( mailmime *mail ); SMTPaccount *getAccount( QString from ); void writeToFile( QString file, mailmime *mail ); void readFromFile( QString file, char **data, size_t *size ); static QString mailsmtpError( int err ); static QString getTmpFile(); Settings *settings; }; #endif |