我需要一个电子邮件解析器,将传入的电子邮件附加到其相应的票证。
如果电子邮件的主题包含票号格式的内容,那么我会搜索它并完成。这已经工作多年了。
现在,我们要按主题搜索匹配的票证标题。
我发现使用正则表达式类从电子邮件主题中删除“RE:”(和类似的东西),这非常适合从传入主题中删除 re: 等。但是,我们有票标题包含
RE:
的情况。我预计它可能包括 FW:
和 FWD:
以及所有这些的混合和小写版本。
找到匹配项的最干净的 Linq 或 SQL 查询是什么?我熟悉
Remove()
。我可以把它们串起来吗?将 16 Removes 串起来以捕获所有案例版本是非常丑陋的,但我想我可以忍受。
而且,这样做的表现如何?我想我可以
ToLower
双方,那应该行得通吗?这可能不会影响我的主题标题匹配。这减少到三个删除。
我确实找到了一页说在查询中使用正则表达式最终会检索所有数据,这可能很昂贵。这也适用于
Remove
吗?我已经通过传入电子邮件地址进行过滤以获得单个客户端,因此我不会对整个数据库运行这些。那么,也许正则表达式是可行的?
还有更好的吗?提醒,我们正在使用实体框架。
谢谢
PS:我知道一些简单的主题可能会被多次点击。 “错误”或“电子邮件问题”。我会按日期降序排列,希望能抓住其中的大部分。
----- 编辑:-----
原谅我,我认为我的描述很透彻。这是一个包含得很好的问题。稍微不同地说,我在 VARCHAR 字段中有一些常见的无关文本片段,我正在寻找最好的方法来搜索忽略那些少数常见文本片段的字段。
这是我的 FindExistingTicket() 方法的当前状态。我已经开始按客户筛选,但在看到这些评论时还没有完成。 (我离开办公桌几个小时。)
/// <summary>
/// Given a from address and a subject, see if we can find a ticket to match.
/// to match. Either the formatted ticket number is in the subject.
/// Or, the subject is identical to a ticket title.
/// </summary>
/// <param name="from">The From address.</param>
/// <param name="subject">The subject string.</param>
/// <returns>The ticket found, or null.</returns>
public Ticket FindExistingTicket(string from, string subject)
{
Ticket ticket = null;
// If the subject is null then there's not going to be a match.
if (subject == null)
{
return null;
}
// First look for a formatted ticket number.
Match m = TicketNumRegex.Match(subject);
if (m.Success)
{
// Make sure a ticket with that number actually exists.
ticket = db.Tickets.Where(a => a.TicketNumber == m.Value).FirstOrDefault();
}
// If we have a ticket, then we're done.
if (ticket != null) return ticket;
// Check to see if we know this email address
Contact contact = db.Contacts.Where(a => a.ContactStatu.Status.Equals("Active") && a.email.ToLower().Contains(from)).FirstOrDefault();
if (contact != null)
{
Client client = db.Clients.Where(a => a.id == contact.customer_id).FirstOrDefault();
// Search for a ticket where the Subject matches the Title.
// First, strip off any re: or Fwd:
// If we want multiple languages, per https://stackoverflow.com/questions/16395814/
// @"^([\[\(] *)?(RE?S?|FYI|RIF|I|FS|VB|RV|ENC|ODP|PD|YNT|ILT|SV|VS|VL|AW|WG|ΑΠ|ΣΧΕΤ|ΠΡΘ|תגובה|הועבר|主题|转发|FWD?) *([-:;)\]][ :;\])-]*|$)|\]+ *$", RegexOptions.IgnoreCase
Regex regex = new Regex(@"^(?>(?:re|fwd|fw) *: *)*", RegexOptions.IgnoreCase);
string strippedSubject = regex.Replace(subject, string.Empty);
// Among open tickets, if we find more than one ticket with this Title, we grab the last one.
List<Ticket> tickets = db.Tickets.Where(a => OpenIDs.Contains(a.Status_ID) && a.Title.Replace("re:", "") == strippedSubject).OrderByDescending(a => a.LastQueueDate).ToList();
if (tickets.Count() >= 1)
{
ticket = tickets.First();
}
}
// else we don't know the email address, so just fall through and return null
return ticket;
}
所以,现在,如果在 SQL 数据库 VARCHAR 字段的票证标题中有一个 RE:,我没有得到匹配项。包含 RE: 和 FW: 的票证标题示例是从电子邮件主题行中手动复制和粘贴的,因此我不会在将它们提交到数据库之前将它们删除。
发布此消息后,当我走出门时,我突然想到,一旦我按客户过滤工单,我的记忆中就会有一个列表。所以,我应该能够在那里廉价地使用正则表达式。也就是说,假设 EF 允许我这样做。
我很高兴听到任何其他想法。