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("? show this help\n");
|
||||||
printf("open <file> open/create database\n");
|
printf("open <file> open/create database\n");
|
||||||
printf("close close 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("set <key> [<value>] set/delete configuration value\n");
|
||||||
printf("get <key> show configuration value\n");
|
printf("get <key> show configuration value\n");
|
||||||
printf("connect connect to mailbox server\n");
|
printf("connect connect to mailbox server\n");
|
||||||
|
@ -125,6 +126,13 @@ int main(int argc, char ** argv)
|
||||||
printf("ERROR: no database opened.\n");
|
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 )
|
else if( strcmp(cmd, "connect")==0 )
|
||||||
{
|
{
|
||||||
if( !mailbox->Connect() ) {
|
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_from = NULL;
|
||||||
carray* contact_ids_to = 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,
|
// 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
|
// 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)
|
// 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 ) {
|
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
|
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.
|
// 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.
|
// 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:
|
private:
|
||||||
char* DecodeHeaderString (const char* in); // can e NULL, result must be free()'s by the caller
|
char* DecodeHeaderString (const char* in); // can e NULL, result must be free()'s by the caller
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#include "mrmailbox.h"
|
#include "mrmailbox.h"
|
||||||
#include "mrimfparser.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
|
* 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.
|
* 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.
|
* 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);
|
MrImfParser parser(this);
|
||||||
|
|
||||||
if( !parser.Imf2Msg(imf, imf_len) ) {
|
if( !parser.Imf2Msg(imf_raw_not_terminated, imf_raw_bytes) ) {
|
||||||
return; // error already logged
|
return; // error already logged
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,12 @@ public:
|
||||||
bool Open (const char* dbfile);
|
bool Open (const char* dbfile);
|
||||||
void Close ();
|
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
|
// empty all tables but leaves server configuration
|
||||||
bool Empty ();
|
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;
|
int r;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
|
@ -651,7 +651,7 @@ carray* MrMimeParser::Parse(const char* body)
|
||||||
Empty();
|
Empty();
|
||||||
|
|
||||||
// parse body
|
// 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 ) {
|
if(r != MAILIMF_NO_ERROR || m_mimeroot == NULL ) {
|
||||||
goto Parse_Cleanup;
|
goto Parse_Cleanup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
// Unless memory-allocation-errors occur, Parse() returns at least one empty part.
|
// 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.
|
// (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)
|
// 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
|
// data, read-only
|
||||||
carray* m_parts;
|
carray* m_parts;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue