首页 > 解决方案 > Applescript 或 Shell 脚本从电子邮件中提取文本和日期并制作日历事件

问题描述

我需要创建一个脚本,该脚本接受格式一致的会议室预订请求 - 名称、日期、时间、持续时间、房间号 - (都在不同的行上),并创建一个包含相同信息的日历事件。它将作为 Apple Mail 中的规则自动运行。

我了解 AppleScript 和 Bash 脚本的基础知识,并且已经广泛研究了这个问题,但我很难过。我可以使用 Automator Quick Action 提取日期,该操作采用所有文本,提取日期,然后将结果传递给此 Applescript,但这仅在指定日期创建日历事件,没有开始或结束时间,并且没有名称和房间号等变量。我无法通过尝试设置和获取这些变量来添加该信息:


on run {input, parameters}

    set dateString to the clipboard
    set start_date to date (dateString)
    set end_date to date (dateString) 

    tell application "Calendar"
        tell calendar "Local"
            make new event at end with properties {summary:"PersonName", start date:start_date, end date:end_date}
        end tell
    end tell 

    return input
end run

任何建议将不胜感激。谢谢。


12-10-18

主持人要求我提供精确格式的示例用例数据。我希望我的反应正确。该数据在电子邮件正文中显示为:

    姓名:[人名]
    日期:[预订日期]
    房间号:[要求的会议室号]
    开始时间:[开始时间]
    结束时间:[结束时间]

标签: bashcalendarapplescriptautomator

解决方案


您有 2 个问题需要解决:1)从电子邮件文本中提取/检查数据 2)从数据中在 iCal 中创建新事件。

您已经完成了第二部分:从数据创建日历事件。

到目前为止,最困难的部分是从电子邮件正文中的非结构化自由文本(甚至值得,因为它是富文本!)中提取数据。这是下面脚本中第一个子程序的作用。

它使用 Applescript 的带有“:”的文本项目分隔符,我添加了其他分隔符,因为电子邮件的内容不是文本,而是富文本(包括返回、换行......)。我假设一行带有“名称”的文本后面必须跟“:”和名称(一个或几个单词)。房间和日期也一样。对于开始/结束时间,该行必须包含“开始”/“结束”,并且在“:”之后,我假设时间设置为小时:分钟。

例如下面的身体是有效的:

Name: Stackoverflow 
Date: 21/12/18 
Start Time: 13:30 
End Time: 15:45
Room Number: Board Room 

注意:这些行可以是任何顺序。这里的房间号是最后一行。

在下面的脚本中,我假设要使用的电子邮件是 Mail 中选择的第一封电子邮件。由你来调整那部分。

property myCalendar : "Local"

tell application "Mail" -- extract the selected email and get its content as list of paragraphs
    set mySelection to selection
    set myMail to first item of mySelection
    set myLines to every paragraph of (content of myMail)
end tell

set myEvent to ExtractfromRichText(myLines) -- parse the paragraphs to make a record {EName, ERoom,EStart,EEnd}
if EName of myEvent is not "" then CreateNewEvent(myCalendar, myEvent)
-- end of main

-- *******************
on ExtractfromRichText(LocalLines) -- convert the rich text with fixed format into a data set
    set AppleScript's text item delimiters to {":", return & linefeed, return, linefeed} -- to remove all rich text end lines
    repeat with aLine in LocalLines
        try
            if text item 1 of aLine contains "Name" then set LName to text item 2 of aLine
            if text item 1 of aLine contains "Date" then set LDate to date (text item 2 of aLine)
            if text item 1 of aLine contains "Room" then set LRoom to text item 2 of aLine
            if text item 1 of aLine contains "Start" then
                copy LDate to LStart
                set hours of LStart to ((text item 2 of aLine) as integer)
                set minutes of LStart to (word 1 of (text item 3 of aLine) as integer)
            end if
            if text item 1 of aLine contains "End" then
                set LEnd to LDate
                set hours of LEnd to ((text item 2 of aLine) as integer)
                set minutes of LEnd to (word 1 of (text item 3 of aLine) as integer)
            end if
        on error -- unexpected format
            log "error"
            return {EName:""} -- not proper email format for calendar events. return empty name
        end try
    end repeat
    return {EName:LName, ERoom:LRoom, EStart:LStart, EEnd:LEnd}
end ExtractfromRichText

-- *******************

on CreateNewEvent(LCalendar, LEvent)
    tell application "Calendar" to tell calendar LCalendar
    make new event at end with properties {summary:EName of LEvent, location:ERoom of LEvent, start date:EStart of LEvent, end date:EEnd of LEvent}
    end tell
end CreateNewEvent

推荐阅读