/*
用到的处理手法 or 收获 or 注意事项:
1. substr函数分离邮箱的用户名和MTA,当需要有两个返回值时,通过传两个引用并改变它们来实现
2.对于map,在使用map[key]前,必须先检查一下key是否存在
如果map不包含key,使用下标有一个危险的副作用,会在map中插入一个key的元素,value取默认值,返回value。也就是说,map[key]不可能返回null
见blog: http://www.cnblogs.com/nzbbody/p/3409298.html
3.在输出时要输出很多空格,所以不妨把5个空格作为一个常量space来输出
4.空格的处理一定要小心谨慎,为此PE过一次
*/
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
//#define debug
using namespace std;
const string space = " ";
void separate(const string &s, string &user, string &mta)
{
int k = s.find('@');
user = s.substr(0, k);
mta = s.substr(k + 1);
}
int main()
{
#ifdef debug
freopen("E:\\in.txt", "r", stdin);
freopen("E:\\out.txt", "w", stdout);
#endif
int k;
string s, t, user1, mta1, user2, mta2;
set<string> addr;
//输入所有MTA,转换为地址列表
while (cin >> s && s != "*") //s为 MTA 而非 *
{
cin >> s >> k;
while (k--)
{
cin >> t;
addr.insert(t + "@" + s);
}
}
while (cin >> s && s != "*") //处理发件人地址
{
separate(s, user1, mta1);
vector<string> mta; //所有需要连接的mta,按照输入排序
map<string, vector<string> > dest; //每个MTA需要发送的客户
set<string> vis;
while (cin >> t && t != "*")
{
separate(t, user2, mta2); //处理收件人地址
if (vis.count(t)) continue; //重复的收件人
vis.insert(t);
if (!dest.count(mta2))
{
mta.push_back(mta2);
dest[mta2] = vector<string> ();
}
dest[mta2].push_back(t);
}
getline(cin, t); //是为了吃掉 * 后的那个回车,也可用 getchar() 代替
string data;
while (getline(cin, t) && t[0] != '*') data += space + t + "\n";
for (int i = 0; i < mta.size(); i++)
{
string mta2 = mta[i];
vector<string> users = dest[mta2];
cout << "Connection between " << mta1 << " and " << mta2 << endl;
cout << space << "HELO " << mta1 << "\n";
cout << space + "250\n";
cout << space + "MAIL FROM:<" + s + ">\n";
cout << space + "250\n";
bool ok = false;
for (int j = 0; j < users.size(); j++)
{
cout << space + "RCPT TO:<" + users[j] << ">\n";
cout << space;
if (addr.count(users[j]))
{
ok = true;
cout << "250\n";
}
else cout << "550\n";
}
if (ok) cout << space + "DATA\n" + space + "354\n" + data + space + ".\n" + space + "250\n";
cout << space + "QUIT\n" + space << "221\n";
}
}
#ifdef debug
fclose(stdin);
fclose(stdout);
#endif
return 0;
}