使用 LotusScript 创建 .ics 日历邀请
Creating an .ics calendar invitation with LotusScript
用例:使用 .ics 文件发送活动邀请,最好使用 LotusScript。
代码在经典的 Domino Web 应用程序中(您知道,$$WebObscureHiddenField),业务逻辑在 LotusScript 中,我不太热衷于编写其他任何东西。
我找到了定义格式的 RFC https://icalendar.org/RFC-Specifications/iCalendar-RFC-5545/ 按照这些约定编写一个文本文件然后附加它似乎很简单。
我在 SO 上看到过类似的问题,Thorsten Link 建议用相关字段填写 'Appointment' 表格,但这似乎有点 'dirty'我.
此处的最佳做法是什么?
一种方法是让 java servlet 实现类似 ical4j 或其他 ics 库的东西,然后动态生成 ics。
我用于发送 ics 文件的其他方法是将必要的字段写入 nics 文件并将其附加到邮件中。
最后我自己构建了 ics 文件;一旦我理解了 RFC,它就非常简单了,我只是不相信任何自动的东西。
Ueli,我给你正确答案了'tickmark'
'/*************************************************************************************
' * CalendarEntry Class
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 21, 2019
' *************************************************************************************/
Class CalendarEntry
Public startdatetime As String
Public enddatetime As String
Public summary As String
Public location As String
Public url As String
Public description As String
' validator: https://icalendar.org/
' spec: https://tools.ietf.org/html/rfc5545
'/*************************************************************************************
' * Function as_NotesStream
' * @return: A NotesStream of the whole file, can be inputted directly into a NotesMimeEntity
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 22, 2019
' *************************************************************************************/
Function as_NotesStream As NotesStream
On Error GoTo ErrorHandler
Dim session As New NotesSession
Dim stream As NotesStream
Set stream = session.Createstream() ' charset Unicode as default
Call stream.WriteText("BEGIN:VCALENDAR", EOL_CRLF)
Call stream.WriteText("PRODID:" & me.prodid(), EOL_CRLF)
Call stream.WriteText("VERSION:2.0", EOL_CRLF)
Call stream.WriteText("METHOD:REQUEST", EOL_CRLF)
' TIMEZONE Section - describes the timezone, the TZID is an internal reference
Call stream.WriteText("BEGIN:VTIMEZONE" , EOL_CRLF)
Call stream.WriteText("TZID:Europe/Berlin" , EOL_CRLF)
Call stream.WriteText("X-LIC-LOCATION:Europe/Berlin" , EOL_CRLF)
Call stream.WriteText("BEGIN:DAYLIGHT" , EOL_CRLF)
Call stream.WriteText("TZOFFSETFROM:+0100" , EOL_CRLF)
Call stream.WriteText("TZOFFSETTO:+0200" , EOL_CRLF)
Call stream.WriteText("TZNAME:CEST" , EOL_CRLF)
Call stream.WriteText("DTSTART:19700329T020000" , EOL_CRLF)
Call stream.WriteText("RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3" , EOL_CRLF)
Call stream.WriteText("END:DAYLIGHT" , EOL_CRLF)
Call stream.WriteText("BEGIN:STANDARD" , EOL_CRLF)
Call stream.WriteText("TZOFFSETFROM:+0200" , EOL_CRLF)
Call stream.WriteText("TZOFFSETTO:+0100" , EOL_CRLF)
Call stream.WriteText("TZNAME:CET" , EOL_CRLF)
Call stream.WriteText("DTSTART:19701025T030000" , EOL_CRLF)
Call stream.WriteText("RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10" , EOL_CRLF)
Call stream.WriteText("END:STANDARD" , EOL_CRLF)
Call stream.WriteText("END:VTIMEZONE" , EOL_CRLF)
Call stream.WriteText("BEGIN:VEVENT", EOL_CRLF)
Call stream.WriteText("SUMMARY:" & me.summary, EOL_CRLF)
' Call stream.WriteText("PRIORITY:0", EOL_CRLF)
' Call stream.WriteText("CATEGORIES:GIG", EOL_CRLF)
Call stream.WriteText("CLASS:PUBLIC", EOL_CRLF)
Call stream.WriteText("UID:" & me.uid(), EOL_CRLF)
Call stream.WriteText("DTSTAMP:" & me.dtstamp(), EOL_CRLF)
Call stream.WriteText("DTSTART;TZID=Europe/Berlin:" & me.startdatetime, EOL_CRLF)
Call stream.WriteText("DTEND;TZID=Europe/Berlin:" & me.enddatetime, EOL_CRLF)
Call stream.WriteText("URL:" & me.url, EOL_CRLF)
Call stream.WriteText("DESCRIPTION:" & prepareTextCorrectly(me.description), EOL_CRLF)
Call stream.WriteText("LOCATION:" & prepareTextCorrectly(me.location), EOL_CRLF)
Call stream.WriteText("END:VEVENT", EOL_CRLF)
Call stream.WriteText("END:VCALENDAR", EOL_CRLF)
Set as_NotesStream = stream
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
'/*************************************************************************************
' * Function domain: the customer-specific domain
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 22, 2019
' *************************************************************************************/
Function domain As String
On Error GoTo ErrorHandler
domain = "example.com"
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
'/*************************************************************************************
' * Function prodid:an id of the producer
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 22, 2019
' *************************************************************************************/
Function prodid As String
On Error GoTo ErrorHandler
prodid = "-//YOUR MEGA PROD_ID//DE"
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
'/*************************************************************************************
' * Function uid:An unique id for the calendar event
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 22, 2019
' *************************************************************************************/
Function uid As String
On Error GoTo ErrorHandler
Dim uuid As Variant
uuid = Evaluate("@Unique")
uid = startdatetime & "-" & CStr(uuid(0)) & "@" & domain
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
'/*************************************************************************************
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 21, 2019
' *************************************************************************************/
Function dtstamp As String
Dim dtTmp As NotesDateTime
Set dtTmp = New NotesDateTime(Now())
Const RFC554FORMATFORUTC = "yyyymmddThhmmssZ"
dtstamp = Format$(dtTmp.lsgmttime, RFC554FORMATFORUTC)
End Function
'/*************************************************************************************
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 21, 2019
' *************************************************************************************/
Function ReplaceCRLFWithSlashN (value As String) As String
Dim CRLF As String
CRLF = Chr$(13) + Chr$(10)
ReplaceCRLFWithSlashN = Replace(value, CRLF, "\n")
End Function
'/*************************************************************************************
' * Function prepareTextCorrectly
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 21, 2019
' *************************************************************************************/
Function prepareTextCorrectly(value As string) As String
On Error GoTo ErrorHandler
prepareTextCorrectly = ReplaceCRLFWithSlashN(value)
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
End Class
回复Andrew Magerman自己的解决方案:
我认为“dtstamp”函数中存在一个小错误,但格式操作的正确模式应该是“yyyymmddThhnnssZ”。
模式的“nn”部分代表“分钟”,而“mm”始终代表“月”。
用例:使用 .ics 文件发送活动邀请,最好使用 LotusScript。
代码在经典的 Domino Web 应用程序中(您知道,$$WebObscureHiddenField),业务逻辑在 LotusScript 中,我不太热衷于编写其他任何东西。
我找到了定义格式的 RFC https://icalendar.org/RFC-Specifications/iCalendar-RFC-5545/ 按照这些约定编写一个文本文件然后附加它似乎很简单。
我在 SO 上看到过类似的问题,Thorsten Link 建议用相关字段填写 'Appointment' 表格,但这似乎有点 'dirty'我.
此处的最佳做法是什么?
一种方法是让 java servlet 实现类似 ical4j 或其他 ics 库的东西,然后动态生成 ics。
我用于发送 ics 文件的其他方法是将必要的字段写入 nics 文件并将其附加到邮件中。
最后我自己构建了 ics 文件;一旦我理解了 RFC,它就非常简单了,我只是不相信任何自动的东西。
Ueli,我给你正确答案了'tickmark'
'/*************************************************************************************
' * CalendarEntry Class
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 21, 2019
' *************************************************************************************/
Class CalendarEntry
Public startdatetime As String
Public enddatetime As String
Public summary As String
Public location As String
Public url As String
Public description As String
' validator: https://icalendar.org/
' spec: https://tools.ietf.org/html/rfc5545
'/*************************************************************************************
' * Function as_NotesStream
' * @return: A NotesStream of the whole file, can be inputted directly into a NotesMimeEntity
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 22, 2019
' *************************************************************************************/
Function as_NotesStream As NotesStream
On Error GoTo ErrorHandler
Dim session As New NotesSession
Dim stream As NotesStream
Set stream = session.Createstream() ' charset Unicode as default
Call stream.WriteText("BEGIN:VCALENDAR", EOL_CRLF)
Call stream.WriteText("PRODID:" & me.prodid(), EOL_CRLF)
Call stream.WriteText("VERSION:2.0", EOL_CRLF)
Call stream.WriteText("METHOD:REQUEST", EOL_CRLF)
' TIMEZONE Section - describes the timezone, the TZID is an internal reference
Call stream.WriteText("BEGIN:VTIMEZONE" , EOL_CRLF)
Call stream.WriteText("TZID:Europe/Berlin" , EOL_CRLF)
Call stream.WriteText("X-LIC-LOCATION:Europe/Berlin" , EOL_CRLF)
Call stream.WriteText("BEGIN:DAYLIGHT" , EOL_CRLF)
Call stream.WriteText("TZOFFSETFROM:+0100" , EOL_CRLF)
Call stream.WriteText("TZOFFSETTO:+0200" , EOL_CRLF)
Call stream.WriteText("TZNAME:CEST" , EOL_CRLF)
Call stream.WriteText("DTSTART:19700329T020000" , EOL_CRLF)
Call stream.WriteText("RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3" , EOL_CRLF)
Call stream.WriteText("END:DAYLIGHT" , EOL_CRLF)
Call stream.WriteText("BEGIN:STANDARD" , EOL_CRLF)
Call stream.WriteText("TZOFFSETFROM:+0200" , EOL_CRLF)
Call stream.WriteText("TZOFFSETTO:+0100" , EOL_CRLF)
Call stream.WriteText("TZNAME:CET" , EOL_CRLF)
Call stream.WriteText("DTSTART:19701025T030000" , EOL_CRLF)
Call stream.WriteText("RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10" , EOL_CRLF)
Call stream.WriteText("END:STANDARD" , EOL_CRLF)
Call stream.WriteText("END:VTIMEZONE" , EOL_CRLF)
Call stream.WriteText("BEGIN:VEVENT", EOL_CRLF)
Call stream.WriteText("SUMMARY:" & me.summary, EOL_CRLF)
' Call stream.WriteText("PRIORITY:0", EOL_CRLF)
' Call stream.WriteText("CATEGORIES:GIG", EOL_CRLF)
Call stream.WriteText("CLASS:PUBLIC", EOL_CRLF)
Call stream.WriteText("UID:" & me.uid(), EOL_CRLF)
Call stream.WriteText("DTSTAMP:" & me.dtstamp(), EOL_CRLF)
Call stream.WriteText("DTSTART;TZID=Europe/Berlin:" & me.startdatetime, EOL_CRLF)
Call stream.WriteText("DTEND;TZID=Europe/Berlin:" & me.enddatetime, EOL_CRLF)
Call stream.WriteText("URL:" & me.url, EOL_CRLF)
Call stream.WriteText("DESCRIPTION:" & prepareTextCorrectly(me.description), EOL_CRLF)
Call stream.WriteText("LOCATION:" & prepareTextCorrectly(me.location), EOL_CRLF)
Call stream.WriteText("END:VEVENT", EOL_CRLF)
Call stream.WriteText("END:VCALENDAR", EOL_CRLF)
Set as_NotesStream = stream
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
'/*************************************************************************************
' * Function domain: the customer-specific domain
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 22, 2019
' *************************************************************************************/
Function domain As String
On Error GoTo ErrorHandler
domain = "example.com"
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
'/*************************************************************************************
' * Function prodid:an id of the producer
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 22, 2019
' *************************************************************************************/
Function prodid As String
On Error GoTo ErrorHandler
prodid = "-//YOUR MEGA PROD_ID//DE"
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
'/*************************************************************************************
' * Function uid:An unique id for the calendar event
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 22, 2019
' *************************************************************************************/
Function uid As String
On Error GoTo ErrorHandler
Dim uuid As Variant
uuid = Evaluate("@Unique")
uid = startdatetime & "-" & CStr(uuid(0)) & "@" & domain
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
'/*************************************************************************************
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 21, 2019
' *************************************************************************************/
Function dtstamp As String
Dim dtTmp As NotesDateTime
Set dtTmp = New NotesDateTime(Now())
Const RFC554FORMATFORUTC = "yyyymmddThhmmssZ"
dtstamp = Format$(dtTmp.lsgmttime, RFC554FORMATFORUTC)
End Function
'/*************************************************************************************
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 21, 2019
' *************************************************************************************/
Function ReplaceCRLFWithSlashN (value As String) As String
Dim CRLF As String
CRLF = Chr$(13) + Chr$(10)
ReplaceCRLFWithSlashN = Replace(value, CRLF, "\n")
End Function
'/*************************************************************************************
' * Function prepareTextCorrectly
' * @author Andrew Magerman/Magerman/NotesNet
' * @version Sep 21, 2019
' *************************************************************************************/
Function prepareTextCorrectly(value As string) As String
On Error GoTo ErrorHandler
prepareTextCorrectly = ReplaceCRLFWithSlashN(value)
Exit Function
ErrorHandler:
Call logError
Exit Function
End Function
End Class
回复Andrew Magerman自己的解决方案:
我认为“dtstamp”函数中存在一个小错误,但格式操作的正确模式应该是“yyyymmddThhnnssZ”。 模式的“nn”部分代表“分钟”,而“mm”始终代表“月”。