1
0
Fork 0
mirror of https://github.com/deltachat/deltachat-core.git synced 2025-10-05 19:42:04 +02:00

Add function to import a single EML-file manually.

This commit is contained in:
B. Petersen 2016-07-29 12:21:00 +02:00
parent 786233634e
commit 17bd12b9e1
7 changed files with 123 additions and 9 deletions

View file

@ -88,6 +88,7 @@ int main(int argc, char ** argv)
printf("? show this help\n");
printf("open <file> open/create database\n");
printf("close close database\n");
printf("import [<spec>] import file/folder/last EML-file(s)\n");
printf("set <key> [<value>] set/delete configuration value\n");
printf("get <key> show configuration value\n");
printf("connect connect to mailbox server\n");
@ -125,6 +126,13 @@ int main(int argc, char ** argv)
printf("ERROR: no database opened.\n");
}
}
else if( strncmp(cmd, "import", 6)==0 )
{
const char* arg1 = strstr(cmd, " ");
if( !mailbox->ImportSpec(arg1? ++arg1 : NULL) ) {
print_error();
}
}
else if( strcmp(cmd, "connect")==0 )
{
if( !mailbox->Connect() ) {

View file

@ -201,7 +201,7 @@ void MrImfParser::AddOrLookupContacts(mailimf_address_list* adr_list, carray* id
******************************************************************************/
int32_t MrImfParser::Imf2Msg(const char* imf_raw, size_t imf_len)
int32_t MrImfParser::Imf2Msg(const char* imf_raw_not_terminated, size_t imf_raw_bytes)
{
carray* contact_ids_from = NULL;
carray* contact_ids_to = NULL;
@ -234,7 +234,7 @@ int32_t MrImfParser::Imf2Msg(const char* imf_raw, size_t imf_len)
// normally, this is done by mailimf_message_parse(), however, as we also need the MIME data,
// we use mailmime_parse() through MrMimeParser (both call mailimf_struct_multiple_parse() somewhen, I did not found out anything
// that speaks against this approach yet)
mime_parser.Parse(imf_raw);
mime_parser.Parse(imf_raw_not_terminated, imf_raw_bytes);
if( mime_parser.m_header == NULL ) {
goto Imf2Msg_Done; // Error - even adding an empty record won't help as we do not know the message ID
}

View file

@ -39,7 +39,7 @@ public:
// Imf2Msg() takes an IMF, convers into one or more messages and stores them in the database.
// the function returns the number of new created messages.
int32_t Imf2Msg (const char* imf, size_t imf_len);
int32_t Imf2Msg (const char* imf_raw_not_terminated, size_t imf_raw_bytes);
private:
char* DecodeHeaderString (const char* in); // can e NULL, result must be free()'s by the caller

View file

@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sqlite3.h>
#include "mrmailbox.h"
#include "mrimfparser.h"
@ -84,6 +85,105 @@ void MrMailbox::Close()
}
/*******************************************************************************
* Import EML-files
******************************************************************************/
bool MrMailbox::ImportFile(const char* filename)
{
bool success = false;
FILE* f = NULL;
struct stat stat_info;
char* data = NULL;
// read file content to `data`
if( (f=fopen(filename, "r")) == NULL ) {
MrLogError("MrMailbox::ImportFile(): Cannot open file.", filename);
goto ImportFile_Cleanup;
}
if( stat(filename, &stat_info) != 0 || stat_info.st_size == 0 ) {
MrLogError("MrMailbox::ImportFile(): Cannot find out file size or file is empty.", filename);
goto ImportFile_Cleanup;
}
if( (data=(char*)malloc(stat_info.st_size))==NULL ) {
MrLogError("MrMailbox::ImportFile(): Out of memory.", filename);
goto ImportFile_Cleanup;
}
if( fread(data, 1, stat_info.st_size, f)!=(size_t)stat_info.st_size ) {
MrLogError("MrMailbox::ImportFile(): Read error.", filename);
goto ImportFile_Cleanup;
}
fclose(f);
f = NULL;
// import `data`
ReceiveImf(data, stat_info.st_size);
// success
success = true;
// cleanup:
ImportFile_Cleanup:
free(data);
if( f ) {
fclose(f);
}
return success;
}
bool MrMailbox::ImportSpec(const char* spec)
{
bool success = false;
char* spec_memory = NULL;
if( !m_sql.Ok() ) {
MrLogError("MrMailbox::ImportSpec(): Datebase not opened.", spec);
goto ImportSpec_Cleanup;
}
// if `spec` is not given, try to use the last one
if( spec == NULL ) {
MrSqlite3Locker locker(m_sql);
spec_memory = m_sql.GetConfig("import_spec", NULL);
spec = spec_memory; // may still be NULL
if( spec == NULL ) {
MrLogError("MrMailbox::ImportSpec(): No file or folder given.", spec);
goto ImportSpec_Cleanup;
}
}
if( strlen(spec)>=4 && strcmp(&spec[strlen(spec)-4], ".eml")==0 ) {
// import a single file
if( !ImportFile(spec) ) {
goto ImportSpec_Cleanup; // error already logged
}
}
else {
// import a directory
MrLogError("MrMailbox::ImportSpec(): Directory import not yet implemented.", spec);
goto ImportSpec_Cleanup;
}
// success
{
MrSqlite3Locker locker(m_sql);
m_sql.SetConfig("import_spec", spec);
}
success = true;
// cleanup
ImportSpec_Cleanup:
free(spec_memory);
return success;
}
/*******************************************************************************
* Connect
******************************************************************************/
@ -135,17 +235,17 @@ bool MrMailbox::Fetch()
/*******************************************************************************
* Receive an IMF as an result to calling Fetch()
* Receive an IMF as an result to calling Fetch() or Import*()
* the new IMF may be old or new and should be parsed, contacts created etc.
* However, the caller should make sure, it does not exist in the database.
******************************************************************************/
void MrMailbox::ReceiveImf(const char* imf, size_t imf_len)
void MrMailbox::ReceiveImf(const char* imf_raw_not_terminated, size_t imf_raw_bytes)
{
MrImfParser parser(this);
if( !parser.Imf2Msg(imf, imf_len) ) {
if( !parser.Imf2Msg(imf_raw_not_terminated, imf_raw_bytes) ) {
return; // error already logged
}
}

View file

@ -64,6 +64,12 @@ public:
bool Open (const char* dbfile);
void Close ();
// ImportSpec() imports data from EML-files. if `spec` is a folder, all EML-files are imported, if `spec` is a file,
// a single EML-file is imported, if `spec` is NULL, the last import is done again (you may want to call Empty() before)
// ImportFile() always imports a single file,
bool ImportSpec (const char* spec);
bool ImportFile (const char* file);
// empty all tables but leaves server configuration
bool Empty ();

View file

@ -642,7 +642,7 @@ void MrMimeParser::ParseMimeRecursive(mailmime* mime)
}
carray* MrMimeParser::Parse(const char* body)
carray* MrMimeParser::Parse(const char* body_not_terminated, size_t body_bytes)
{
int r;
size_t index = 0;
@ -651,7 +651,7 @@ carray* MrMimeParser::Parse(const char* body)
Empty();
// parse body
r = mailmime_parse(body, strlen(body), &index, &m_mimeroot);
r = mailmime_parse(body_not_terminated, body_bytes, &index, &m_mimeroot);
if(r != MAILIMF_NO_ERROR || m_mimeroot == NULL ) {
goto Parse_Cleanup;
}

View file

@ -55,7 +55,7 @@ public:
// Unless memory-allocation-errors occur, Parse() returns at least one empty part.
// (this is because we want to add even these message to our database to avoid reading them several times.
// of course, these empty messages are not added to any chat)
carray* Parse (const char* body);
carray* Parse (const char* body_not_terminated, size_t body_bytes);
// data, read-only
carray* m_parts;