MailImporter

filtermbox.cpp
1/*
2 filtermbox.cpp - mbox mail import
3
4 SPDX-FileCopyrightText: 2003 Laurence Anderson <l.d.anderson@warwick.ac.uk>
5
6 SPDX-License-Identifier: GPL-2.0-or-later
7*/
8
9#include "filtermbox.h"
10#include "mailimporter_debug.h"
11
12#include <KLocalizedString>
13
14#include <QFileDialog>
15#include <QTemporaryFile>
16
17using namespace MailImporter;
18
19FilterMBox::FilterMBox()
20 : Filter(i18n("Import mbox Files (UNIX, Evolution)"),
21 i18n("Laurence Anderson <p>( Filter accelerated by Danny Kukawka )</p>"),
22 i18n("<p><b>mbox import filter</b></p>"
23 "<p>This filter will import mbox files into KMail. Use this filter "
24 "if you want to import mails from Ximian Evolution or other mailers "
25 "that use this traditional UNIX format.</p>"
26 "<p><b>Note:</b> Emails will be imported into folders named after the "
27 "file they came from, prefixed with MBOX-</p>"))
28{
29}
30
31FilterMBox::~FilterMBox()
32{
33}
34
35void FilterMBox::import()
36{
37 const QStringList filenames =
38 QFileDialog::getOpenFileNames(filterInfo()->parentWidget(), QString(), QDir::homePath(), QStringLiteral("%1 (*.mbox)").arg(i18n("mbox Files")));
39 importMails(filenames);
40}
41
42void FilterMBox::importMails(const QStringList &filenames)
43{
44 if (filenames.isEmpty()) {
45 filterInfo()->alert(i18n("No files selected."));
46 return;
47 }
48 int currentFile = 1;
49 int overall_status = 0;
50 bool first_msg = true;
51
52 filterInfo()->setOverall(0);
53
55 for (QStringList::ConstIterator filename = filenames.constBegin(); filename != end; ++filename, ++currentFile) {
56 QFile mbox(*filename);
57 if (!mbox.open(QIODevice::ReadOnly)) {
58 filterInfo()->alert(i18n("Unable to open %1, skipping", *filename));
59 } else {
60 QFileInfo filenameInfo(*filename);
61 QString folderName(QStringLiteral("MBOX-%1").arg(filenameInfo.completeBaseName()));
62
63 filterInfo()->setCurrent(0);
64 filterInfo()->addInfoLogEntry(i18n("Importing emails from %1...", *filename));
65
66 filterInfo()->setFrom(*filename);
67 filterInfo()->setTo(folderName);
68
69 QByteArray input(MAX_LINE, '\0');
70 long l = 0;
71
72 while (!mbox.atEnd()) {
74 tmp.open();
75 qint64 filepos = 0;
76 /* comment by Danny:
77 * Don't use QTextStream to read from mbox, better use QDataStream. QTextStream only
78 * support Unicode/Latin1/Locale. So you lost information from emails with
79 * charset!=Unicode/Latin1/Locale (e.g. KOI8-R) and Content-Transfer-Encoding != base64
80 * (e.g. 8Bit). It also not help to convert the QTextStream to Unicode. By this you
81 * get Unicode/UTF-email but KMail can't detect the correct charset.
82 */
83 QByteArray separate;
84
85 /* check if the first line start with "From " (and not "From: ") and discard the line
86 * in this case because some IMAP servers (e.g. Cyrus) don't accept this header line */
87 if (!first_msg && ((separate = input.data()).left(5) != "From ")) {
88 tmp.write(input.constData(), l);
89 }
90
91 l = mbox.readLine(input.data(), MAX_LINE); // read the first line, prevent "From "
92
93 if ((separate = input.data()).left(5) != "From ") {
94 tmp.write(input.constData(), l);
95 }
96
97 while (!mbox.atEnd() && (l = mbox.readLine(input.data(), MAX_LINE)) && ((separate = input.data()).left(5) != "From ")) {
98 tmp.write(input.constData(), l);
99
100 // workaround to fix hang if a corrupted mbox contains some
101 // binary data, for more see bug #106796
102 if (mbox.pos() == filepos) {
103 mbox.seek(mbox.size());
104 } else {
105 filepos = mbox.pos();
106 }
107 }
108 tmp.flush();
109 first_msg = false;
110
111 if (tmp.size() > 0) {
112 if (!importMessage(folderName, tmp.fileName(), filterInfo()->removeDupMessage())) {
113 filterInfo()->addErrorLogEntry(i18n("Could not import %1", tmp.fileName()));
114 }
115 } else {
116 qCWarning(MAILIMPORTER_LOG) << "Message size is 0 bytes, not importing it.";
117 }
118
119 int currentPercentage = (int)(((float)mbox.pos() / filenameInfo.size()) * 100);
120 filterInfo()->setCurrent(currentPercentage);
121 if (currentFile == 1) {
122 overall_status = (int)(currentPercentage * ((float)currentFile / filenames.count()));
123 } else {
124 overall_status = (int)(((currentFile - 1) * (100.0 / (float)filenames.count())) + (currentPercentage * (1.0 / (float)filenames.count())));
125 }
126 filterInfo()->setOverall(overall_status);
127
128 if (filterInfo()->shouldTerminate()) {
129 break;
130 }
131 }
132
133 filterInfo()->addInfoLogEntry(i18n("Finished importing emails from %1", *filename));
134 if (countDuplicates() > 0) {
135 filterInfo()->addInfoLogEntry(i18np("1 duplicate message not imported to folder %2 in KMail",
136 "%1 duplicate messages not imported to folder %2 in KMail",
137 countDuplicates(),
138 folderName));
139 }
140 if (filterInfo()->shouldTerminate()) {
141 filterInfo()->addInfoLogEntry(i18n("Finished import, canceled by user."));
142 }
143
144 clearCountDuplicate();
145 // don't forget to close the file !!!
146 mbox.close();
147 }
148 }
149}
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
const QList< QKeySequence > & end()
QString homePath()
virtual qint64 size() const const override
bool flush()
QStringList getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
qint64 write(const QByteArray &data)
typedef ConstIterator
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
bool isEmpty() const const
virtual QString fileName() const const override
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:39 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.