如何程序从outlook express中提取出邮件,然后将邮件批量发出

xiao234666 2008-03-01 02:18:43
to:ccrun(老妖)
以前在类似的帖子里看见过你这方面的解答,我得到一段代码,但我运行时提示CreateOleObject()这个函数存在如下错误提示:
"ambiguity between '_fastcall comobj::createOleObject(const system::ansistring)' and '_fastcall oleauto::createOleObject(const system::ansistring)'"

  我猜想可能缺少某个头文件,但查了下资料一直没有找到这个头文件,希望得到你或大家的解答.

  还有一个问题就是:当我从outlook express中提取出了邮件后,假定得到了每封邮件的发件人,收件人,发送时间,信件内容等这些信件信息后,如何将它们再发送出去呢(发送邮件的代码希望大家能给些提示)?或许大家会有疑问,为什么得到了又要发出去呢?这是因为,我现在做一个模拟实验,需要借助outlook express这个软件方便得到大量邮件来完成我的实验.举个例子说明我到底想要干什么:
  如我在outlook express中有一封发件人为"11111@163.com",收件人为"22222@126.com",发送时间为"2008年3月1日 10:00",的信件;现在我要将这封信发到我架设的一个邮件服务器上的一个邮箱,架设这个邮箱为"xxxxx@xx.com";我就将此封信件的发件人改为"邮件服务器上除用户名为xx的任意有效用户名@xx.com",收件人改为"22222@xx.com",向邮件服务器发出该邮件
...全文
1021 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
MEFULEU 2008-04-17
  • 打赏
  • 举报
回复
学写了~~~
xiao234666 2008-03-02
  • 打赏
  • 举报
回复
我现在的想法是,将每封邮件都转换成.eml格式的文件(是个文本文件),然后我在此文本文件中通过特征字符串的查找,如找"From:"就能得到紧跟其后的发件人地址.类似通过此方法,找出收件人,以及发送时间.

  我现在的问题就是,如何将该.eml格式的文件,原封不动地再发送出去(即发送时间不能发生变化).如:我将一封保存成.eml的信通过上段提到的方法提出了发件人(xx@163.com),收件人(yy@163.com),发送时间(2005年8月31日10:50)这三个信息,然后我将发件人和收件人信息都改为另外的地址,而发送时间还是2005年8月31日10:50.这样发送到指定邮箱里.
xiao234666 2008-03-02
  • 打赏
  • 举报
回复
感谢ccrun为我找的资料!!
我读了半天,感觉看起来不怎么明白而且还好吃力,我现在把每封邮件都转换成了.eml格式的文件,不知道能否用程序读.eml格式的文件得出发件人,收件人,主题,信件内容,以及附件等内容.
ccrun.com 2008-03-01
  • 打赏
  • 举报
回复

// dbx_EnsureFolders: first builds up a FolderSorting tree. Then calls
// the above function to copy it into the flat global vector.
//
void dbx_EnsureFolders(const string name,const string ver)
{ string testn=name, testv=ver;
if (testn=="") testn="_"; if (testv=="") testv="_";
if (dbx_DoneFoldersName==testn && dbx_DoneFoldersVer==testv) return;
dbx_DoneFoldersName=testn; dbx_DoneFoldersVer=testv;
dbx_Folders.clear();
if (dbx_DoneStores=="") dbx_EnsureStores(name);
//
// Now let's find the path for this name/ver
string path="";
for (vector<TDbxStore>::iterator i=dbx_Stores.begin(); i!=dbx_Stores.end(); i++)
{ if (name=="" && ver=="") {path=i->path; break;}
else if (name==i->name && ver==i->ver) {path=i->path; break;}
}
if (path=="") return;
string ffn = path+"\\Folders.dbx";
if (!FileExists(ffn)) return;

// Folders.dbx is an index of the folders in this profile.
// It is a flat list. Each entry has:
// id, parent-id, fn, name, regstring, subindex, value, id0b
// The id/parent-id determine the structure of the tree
// name is the folder name, and fn is the dbx filename (as a sub of path)
// For top-level ones, we look at regstring to determine the index:
// "LocalStore" is 1, some others also have numbers, some are empty (in which case we use index in the file)
// For sub-level ones, some have subindex set, some are empty (in which case we use index in the file)
// If value is 1, or if id0b is 0x2F0000, then this might be an offlineable folder.
vector<TDbxFolderSorting*> folders;
map<unsigned int,TDbxFolderSorting*> i2f;
//
// I'm using my specialised memory-mapped class here.
// Arne's code was written to use an istream instead, so you'll
// have to either change this to an istream, or change Arne's code.
imemfile inm(ffn.c_str());
if (!inm.okay()) return;
DbxFileHeader fileHeader(inm);

const int4 treeNumber=2; // This third tree stores pointers to all folder informations
int4 address = fileHeader.GetValue(fhTreeRootNodePtr+treeNumber);
int4 entries = fileHeader.GetValue(fhEntries +treeNumber);
if(address && entries)
{ DbxTree tree(inm,address,entries); // Read in the tree with all pointers
for(int4 filepos=0; filepos<entries; ++filepos)
{ int1 *ptr; int4 length;
address = tree.GetValue(filepos); // Get the address of the folder info
DbxFolderInfo folderInfo(inm,address); // Read in the folder info
unsigned int index = folderInfo.GetValue(0);
unsigned int pindex = folderInfo.GetValue(1);
string fn; ptr=folderInfo.GetValue(3,&length); if (ptr!=0 && length>0) fn=string((char*)ptr,length-1);
string name; ptr=folderInfo.GetValue(2,&length); if (ptr!=0 && length>0) name=string((char*)ptr,length-1);
string reg; ptr=folderInfo.GetValue(5,&length); if (ptr!=0 && length>0) reg=string((char*)ptr,length-1);
unsigned int pos = folderInfo.GetValue(9);
unsigned int value = folderInfo.GetValue(10);
unsigned int id0b = folderInfo.GetValue(11);
unsigned int num_to_download = folderInfo.GetValue(18);
//
bool isexplicitpos=false;
if (strncmp(reg.c_str(),"LocalStore",10)==0) reg="1";
if (reg!="" && pindex==0)
{ bool isnum=true; for (unsigned int i=0; i<reg.length(); i++) {if (reg[i]<'0' || reg[i]>'9') isnum=false;}
if (isnum) sscanf(reg.c_str(),"%lu",&pos);
}
if (pos!=0) isexplicitpos=true; else pos=filepos;
TDbxFolderSorting *parent=0;
if (pindex!=0)
{ map<unsigned int,TDbxFolderSorting*>::const_iterator i = i2f.find(pindex);
if (i!=i2f.end()) parent=i->second;
}
bool isnews = (value==0);
//
if (!isnews)
{ TDbxFolderSorting *f = new TDbxFolderSorting;
f->index = index;
f->isexplicitpos = isexplicitpos;
f->position = pos;
f->info.name = name;
f->parent = parent;
if (parent==0 || parent->parent==0) f->info.path="";
else if (parent->info.path=="") f->info.path=parent->info.name;
else f->info.path=parent->info.path+"\\"+parent->info.name;
if (parent==0) f->info.account="";
else if (parent->parent==0) f->info.account=parent->info.name;
else f->info.account=parent->info.account;
string sf="";
if (f->info.account!="") sf += f->info.account+"\\";
if (f->info.path!="") sf += f->info.path+"\\";
sf += f->info.name;
f->info.full = sf;
f->info.fn = fn;
f->info.fpath = path;
if (parent==0) f->info.depth=0; else f->info.depth=parent->info.depth+1;
if (parent==0) f->info.type=dftStructure;
else if (!f->isexplicitpos) f->info.type=dftMail;
else if (pos==1) f->info.type=dftInbox;
else if (pos==2) f->info.type=dftOutbox;
else if (pos==3) f->info.type=dftSent;
else if (pos==4) f->info.type=dftDeleted;
else if (pos==5) f->info.type=dftDrafts;
else f->info.type=dftMail;
f->info.might_contain_offlines = (value==0 || value==1 || id0b==0x2F || num_to_download>0);
// That 'num to download' isn't reliable.
//
if (parent==0) folders.push_back(f);
else parent->c.push_back(f);
i2f.insert(pair<unsigned int,TDbxFolderSorting*>(index,f));
}
}
}
inm.close();

// Now sort them and save copies into the main list ane delete them
RecEnsureFolders(folders,true);
}

imemfile::imemfile(const char *fn)
{ buf=0; isokay=false; pos=0; hf=0; hmap=0; size=0; DWORD high;
if (fn!=0) hf = CreateFile(fn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (hf==INVALID_HANDLE_VALUE) isokay=false;
else size=GetFileSize(hf,&high);
if (high!=0 || size==0) {CloseHandle(hf);hf=0; isokay=false;}
else hmap=CreateFileMapping(hf,NULL,PAGE_READONLY,0,0,NULL);
if (hmap==NULL) {CloseHandle(hf); hf=0; isokay=false;}
else buf=(const char*)MapViewOfFile(hmap,FILE_MAP_READ,0,0,0);
if (buf==0) {CloseHandle(hmap); hmap=0; CloseHandle(hf); hf=0; isokay=false;}
else isokay=true;
}

imemfile::~imemfile()
{ close();
}

void imemfile::seekg(unsigned int apos)
{ if (buf==0 || apos>size) isokay=false; else pos=apos;
}

void imemfile::read(char *dst,unsigned int rsize)
{ if (buf==0 || pos+rsize>size) isokay=false;
else {memcpy(dst,buf+pos,rsize); pos+=rsize;}
}

bool imemfile::okay()
{ return isokay;
}

void imemfile::close()
{ if (buf!=0) UnmapViewOfFile(buf); buf=0;
if (hmap!=0) CloseHandle(hmap); hmap=0;
if (hf!=0) CloseHandle(hf); hf=0;
size=0; pos=0; isokay=false;
}

// IsValidDbxFile: to tell whether a given file is a valid DBX file
//
bool IsValidDbxFile(const string fn,bool wantfolders)
{ HANDLE hf = CreateFile(fn.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (hf==INVALID_HANDLE_VALUE) return false;
DWORD high; DWORD size=GetFileSize(hf,&high);
CloseHandle(hf);
if (high!=0 || size<FileHeaderSize) return false;
bool okay=false;
imemfile inm(fn.c_str());
try
{ DbxFileHeader fileHeader(inm);
int4 length = fileHeader.GetValue(fhFileInfoLength);
int4 address = FileHeaderSize;
if (length+FileHeaderSize<=size)
{ DbxFileInfo inf(inm,address,length);
if (wantfolders) okay=fileHeader.isFolders();
else okay=!fileHeader.isFolders();
}
}
catch (...)
{
}
inm.close();
return okay;
}

bool IsValidDbxFolderFile(const string fn) {return IsValidDbxFile(fn,true);}
bool IsValidDbxMessageFile(const string fn) {return IsValidDbxFile(fn,false);}
ccrun.com 2008-03-01
  • 打赏
  • 举报
回复
Source-code 'dbx_utils.cpp'

#include <windows.h>
#include <string>
#include <list>
#include <vector>
using namespace std;
#pragma hdrstop // precompiled headers stop here
#include "dbx_utilsh"

vector<TDbxStore> dbx_Stores;

void dbx_EnsureStores()
{ dbx_Stores.clear();

// We'll build up a list of things in
// HKEY_CURRENT_USER\Identities\<id>\Software\Microsoft\Outlook Express\<ver>
// Except we start the default identity first, and the rest in order;
// and we store the versions in descending order.
// So: MainIdentity\5.0
// MainIdentity\4.0
// SecondIdentity\5.0
// SecondIdentity\4.0
// Incidentally, if multiple different versions all point to the same store
// folder, then we collapse them, and only display the most recent version.
HKEY key; LONG res;
res = RegOpenKeyEx(HKEY_CURRENT_USER,"Identities",0,KEY_READ,&key);
if (res!=ERROR_SUCCESS) return;
list<string> ids = RegQuerySubkeys(key);
string defid = RegQueryString(key,"Default User ID");
RegCloseKey(key);
if (ids.size()==0) return;
//
for (int pas=0; pass<2; pass++)
{ // in pass=0 we add only the default id.
// in pass=1 we add all other ids
for (list<string>::iterator i=ids.begin(); i!=ids.end(); i++)
{ string id = *i; string name; string s; list<string> vers; bool okay = true;
if (okay)
{ if (pass==0 && id!=defid) okay=false;
else if (pass==1 && id==defid) okay=false;
}
if (okay)
{ res = RegOpenKeyEx(HKEY_CURRENT_USER,("Identities\\"+id).c_str(),0,KEY_READ,&key);
if (res!=ERROR_SUCCESS) okay=false;
else {name = RegQueryString(key,"Username"); RegCloseKey(key);}
if (name=="") okay=false;
}
if (okay)
{ s = "Identities\\"+id+"\\Software\\Microsoft\\Outlook Express";
res = RegOpenKeyEx(HKEY_CURRENT_USER,s.c_str(),0,KEY_READ,&key);
if (res!=ERROR_SUCCESS) okay=false;
else {vers = RegQuerySubkeys(key); RegCloseKey(key);}
}
for (list<string>::reverse_iterator j=vers.rbegin(); okay && j!=vers.rend(); j++)
{ string ver = *j; string path="";
res = RegOpenKeyEx(HKEY_CURRENT_USER,(s+"\\"+ver).c_str(),0,KEY_READ,&key);
if (res==ERROR_SUCCESS) {path = RemoveTrailingSlash(RegQueryString(key,"Store Root")); RegCloseKey(key);}
if (path!="")
{ // If different versions of OE are installed, but all point to the same location,
// then we won't add them
bool alreadythere=false;
if (dbx_Stores.size()>0)
{ TDbxStore &prevdbx = dbx_Stores.back();
if (prevdbx.id==id && StringLower(prevdbx.path)==StringLower(path)) alreadythere=true;
}
if (!alreadythere && FileExists(path+"\\Folders.dbx"))
{ TDbxStore dbxs;
dbxs.id = id;
dbxs.name = name;
dbxs.ver = ver;
dbxs.path = path;
dbx_Stores.push_back(dbxs);
}
}
}
}
}
}

vector<TDbxFolderInfo> dbx_Folders;
string dbx_DoneFoldersName, dbx_DoneFoldersVer;
// This 'TDbxFolderSorting' is used to sort the folders we retrieve
// into an order approximating that of Outlook Express
class TDbxFolderSorting
{ public:
unsigned int index;
bool isexplicitpos; unsigned int position;
TDbxFolderInfo info;
vector<TDbxFolderSorting*> c;
TDbxFolderSorting *parent;
};
bool comp(const TDbxFolderSorting *a,const TDbxFolderSorting *b)
{ if (b==NULL) return true; else if (a==NULL) return false;
if (a->isexplicitpos && !b->isexplicitpos) return true; else if (!a->isexplicitpos && b->isexplicitpos) return false;
if (a->position<b->position) return true; else if (a->position>b->position) return false;
return true;
}

// RecEnsureFolders -- this function recursively deletes the
// FolderSorting, and at the same time copies bits into the dbx_Folders
// global vector
void RecEnsureFolders(vector<TDbxFolderSorting*> &s,bool addit)
{ sort(s.begin(), s.end(), comp);
for (vector<TDbxFolderSorting*>::iterator i=s.begin(); i!=s.end(); i++)
{ TDbxFolderSorting *f = *i;
bool laddit=addit;
if (f->info.type==dftOutbox || f->info.type==dftDeleted || f->info.type==dftDrafts) laddit=false;
if (laddit) dbx_Folders.push_back(f->info);
RecEnsureFolders(f->c,laddit); // we need to call it recursively, even if !addit, since that will also delete stuff
delete f;
}
}
ccrun.com 2008-03-01
  • 打赏
  • 举报
回复
饭毕归来。仔细看了一下你的需求,好象有些复杂,我以前写的代码是针对Office套件中的Outlook的,所以当系统中没有安装OutLook时(不是OS自带的outlook express),会提示"Invalid class string"。刚才又找了找资料,貌似没有找到官方的API或接口什么的。只找到以前收藏的一篇文档,有些长,我没时间仔细研究,你自个看看吧。原作者不详,不过应该是国外某个人写的。

Outlook Express example code for getting a list of profiles and folders
获取Outlook中的联系人和文件夹列表

(c) 2002 Lucian Wischik. This code is free, and anyone can do with it whatever they like (except sell it or claim ownership).

Outlook Express stores its mailfolders and newsfolders in DBX file format. Arne Shloh has figured out the important bits of the DBX file format. He has written documentation and code on reading DBX files, available at his web site http://oedbx.aroh.de. His code is exceptionally clear and well-written.

Once you have his code, all you need is to figure out which identities are on the computer, and where they're stored. This web page contains code to help with that.

The way it works is that Outlook Express may have several 'Identities'. You manage identities on the File | Identities menu. Furthermore, each identity may serve several different email accounts, managed on the Tools | Accounts menu. Now, each identity stores all of its folders in a single directory somewhere on the hard disk. In this directory, there is a special file called FOLDERS.DBX which contains a list of all the mailfolders. And each mailfolder is stored in its own DBX file.

The code on this page reads from the registry to find out where those folders are located.

Header-file 'dbx_utils.h'#ifndef dbx_utilsH

#define dbx_utilsH

// dbx_EnsureStores: call this function to build up the global
// variable 'dbx_Stores', which is a vector containing all the
// Outlook Express identities on this machine.
void dbx_EnsureStores();

// dbx_EnsureFolders: call this to build up the global
// variable 'dbx_Folders', a vector containing all the
// folders for a given OE idententy
void dbx_EnsureFolders(const string name,const string ver);

// These functions test whether a file is a valid dbx file
bool IsValidDbxFolderFile(const string fn);
bool IsValidDbxMessageFile(const string fn);

enum TDbxFolderType {dftStructure, dftInbox, dftOutbox, dftSent, dftDeleted, dftDrafts, dftMail};

typedef struct
{ string id; // e.g. {CAA16-...}
string name; // the username, e.g. "Main Identity"
string ver; // the version of Outlook Express, e.g. "5.0"
string path; // the path to the store root, e.g. "c:\\store"
} TDbxStore;

typedef struct
{ string name; // e.g. "Joseph"
string path; // e.g. "Friends"
string account; // e.g. "Cambridge email";
string full; // e.g. "Cambridge Email\\Friends\\Joseph"
string fn; // e.g. "cambridge email - inbox.dbx"
string fpath; // e.g. "c:\\localmessagestore"
unsigned int depth; // e.g. 2 (Cam.Email=0, Friends=1, Joseph=2)
TDbxFolderType type; // see the above enumeration
bool might_contain_offlines; // just a hint
DWORD filesize; // this gets set at a later time, during processing
} TDbxFolderInfo;
bool operator <(const TDbxFolderInfo &a,const TDbxFolderInfo &b);

extern vector<TDbxStore> dbx_Stores;
extern vector<TDbxFolderInfo> dbx_Folders;

// imemfile: this is similar to the STL 'istream' class, but
// is for Windows and is for memory-mapping a read-only file.
// I tweaked Arne's dbx code a little, to make it use these
// memory-mapped files, for an appreciable speed gain.
//
class imemfile
{ public:
const char *buf; DWORD size;
imemfile(const char *fn);
~imemfile();
void close();
void seekg(unsigned int apos);
void read(char *dst, unsigned int size);
bool okay();
protected:
unsigned int pos;
bool isokay;
HANDLE hf;
HANDLE hmap;
};

703

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder ActiveX/COM/DCOM
社区管理员
  • ActiveX/COM/DCOM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧