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:
parent
786233634e
commit
17bd12b9e1
7 changed files with 123 additions and 9 deletions
|
@ -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() ) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue