def _ical_serialize_av_alarm(record): alarm = icalendar.Alarm() alarm.add('trigger', timedelta(minutes=-int(record['_ical_alarm']))) alarm.add('action', 'DISPLAY') alarm.add('summary', _ical_summary(record)) alarm.add('description', str(record['url'])) return alarm
def new_event(locale, dtstart=None, dtend=None, summary=None, timezone=None, allday=False, description=None, location=None, categories=None, repeat=None, until=None, alarms=None): """create a new event :param dtstart: starttime of that event :type dtstart: datetime :param dtend: end time of that event, if this is a *date*, this value is interpreted as being the last date the event is scheduled on, i.e. the VEVENT DTEND will be *one day later* :type dtend: datetime :param summary: description of the event, used in the SUMMARY property :type summary: unicode :param timezone: timezone of the event (start and end) :type timezone: pytz.timezone :param allday: if set to True, we will not transform dtstart and dtend to datetime :type allday: bool :returns: event :rtype: icalendar.Event """ if dtstart is None: raise ValueError("no start given") if dtend is None: raise ValueError("no end given") if summary is None: raise ValueError("no summary given") if not allday and timezone is not None: dtstart = timezone.localize(dtstart) dtend = timezone.localize(dtend) event = icalendar.Event() event.add('dtstart', dtstart) event.add('dtend', dtend) event.add('dtstamp', datetime.now()) event.add('summary', summary) event.add('uid', generate_random_uid()) # event.add('sequence', 0) if description: event.add('description', description) if location: event.add('location', location) if categories: event.add('categories', categories) if repeat and repeat != "none": rrule = rrulefstr(repeat, until, locale) event.add('rrule', rrule) if alarms: for alarm in alarms.split(","): alarm = alarm.strip() alarm_trig = -1 * guesstimedeltafstr(alarm) new_alarm = icalendar.Alarm() new_alarm.add('ACTION', 'DISPLAY') new_alarm.add('TRIGGER', alarm_trig) new_alarm.add('DESCRIPTION', description) event.add_component(new_alarm) return event
def create_alarm(): # Create a alarm which will notify user 20 minutes before the occur time. alarm = icalendar.Alarm() alarm.add("action", "DISPLAY") alarm.add("trigger", datetime.timedelta(minutes = -20)) alarm.add("description", "Event reminder") return alarm
def cal_create(lsns_list, cal_temp_list): cal = icalendar.Calendar() # cal.add('prodid', 'test_prodid') # cal.add('version', '2.0') for lsn in lsns_list: # lsn_name = '日程名' # srt_time = datetime.datetime(2018, 1, 22, 8, 0, 0, tzinfo=tz) # end_time = datetime.datetime(2018, 1, 22, 10, 0, 0, tzinfo=tz) # lct = 'somewhere1' alerm_info = icalendar.Alarm() alerm_info.add('action', 'dispaly') alerm_info.add('trigger', datetime.timedelta(minutes=-90)) alerm_info.add('discription', 'Reminder') e = icalendar.Event() for i in cal_temp_list: e.add(i, lsn[i]) e.subcomponents = [alerm_info] cal.add_component(e) f = open('C:\\result.ics', 'wb') f.write(cal.to_ical()) f.close()
def sendmail(organizer,location,starttime,endtime,to,attendees,subject,method): #tz = pytz.timezone("Asia/Shanghai") #start = tz.localize(start) #end = tz.localize(end) print "send mail to ", organizer,location,starttime,endtime,attendees,subject,to,method msg = email.MIMEMultipart.MIMEMultipart() #body = email.MIMEText.MIMEText(MESSAGE.replace('XX', name), 'html', 'utf-8') #msg.attach(body) #''' cal = icalendar.Calendar() cal.add('prodid', '-//My calendar application//example.com//') cal.add('version', '2.0') cal.add('method', method) event = icalendar.Event() attendees.append(to) for attendee in attendees: event.add('attendee', 'MAILTO:' + attendee) event.add('organizer', organizer) event.add('location', location) event.add('dtstart', datetime.strptime(starttime, "%Y.%m.%d %H:%M")) event.add('dtend', datetime.strptime(endtime, "%Y.%m.%d %H:%M")) event['uid'] = uid(organizer + location + starttime + to) # Generate some unique ID print 'uid=', event['uid'] event.add('priority', 5) event.add('sequence', 1) event.add('created', datetime.now()) alarm = icalendar.Alarm() alarm.add("action", "DISPLAY") alarm.add('description', "Reminder") #alarm.add("trigger", dt.timedelta(hours=-reminderHours)) # The only way to convince Outlook to do it correctly alarm.add("TRIGGER;RELATED=START", "-PT{0}M".format(15)) event.add_component(alarm) cal.add_component(event) filename = "invite.ics" part = email.MIMEBase.MIMEBase('text', "calendar", method=method, name=filename) part.set_payload( cal.to_ical() ) email.Encoders.encode_base64(part) part.add_header('Content-Description', filename) part.add_header("Content-class", "urn:content-classes:calendarmessage") part.add_header("Filename", filename) part.add_header("Path", filename) msg.attach(part) msg.add_header('X-Priority', '1') msg.add_header('From', SMTP_USERNAME) msg.add_header('To', to) subject = Header(subject, 'utf-8') msg['Subject'] = subject # Now send the message mailer = smtplib.SMTP(SMTP_SERVER, int(SMTP_PORT)) mailer.login(SMTP_USERNAME, SMTP_PASSWORD) mailer.sendmail(SMTP_USERNAME, attendees, msg.as_string()) mailer.close()
def calendar_ics(slug, name): try: cal = Calendar.query.filter_by(slug=slug).one() except sqlalchemy.orm.exc.NoResultFound: abort(404) root = ics.Calendar() def make_zulu(dt): dtz = dt.astimezone(pytz.UTC) return dtz fromstr = parse_from(request.args.get("from") or "-31d") fromdt = datetime.now() + fromstr events = (Event.query.join(CalendarSource).filter_by( calendar=cal).filter(Event.start >= fromdt).order_by( Event.start.desc())) for dbevent in events: event = ics.Event() event.add("summary", dbevent.summary) event.add("uid", dbevent.uid) event.add("description", dbevent.description or "") event.add("location", dbevent.location or "") event.add("url", dbevent.url or "") dtstart = make_zulu(dbevent.start) dtend = make_zulu(dbevent.end) if dbevent.source.all_day_override and dtstart.date( ) != dtend.date(): app.logger.debug("Override start %s -> %s", dtstart, dtstart.date()) app.logger.debug("Override end %s -> %s", dtend, dtend.date()) event.add("dtstart", dtstart.date()) event.add("dtend", dtend.date() + timedelta(days=1)) else: event.add("dtstart", dtstart) event.add("dtend", dtend) event.add("dtstamp", make_zulu(dbevent.timestamp)) # add alarms if dbevent.source.alerts != "": for mins in dbevent.source.alerts.split(";"): # app.logger.debug(mins) # td = timedelta(minutes=int(mins)) # alarmtime = dtstart - td alarm = ics.Alarm() # alarm.add("trigger", alarmtime) # alarm.add("trigger", "-PT{}M".format(mins)) alarm["TRIGGER"] = "-PT{}M".format(mins) alarm.add("action", "DISPLAY") event.add_component(alarm) root.add_component(event) return root.to_ical()
def output(cal_name, cal_data, exam_lst, firstMonday): ical = icalendar.Calendar() ical["verison"] = "2.0" ical["x-wr-calname"] = cal_name # parse class for day in range(0, 7): for time_pnt in range(0, 6): for each_class in cal_data[day][time_pnt]: try: for week in each_class["weeks"]: target_date = firstMonday + datetime.timedelta(weeks=week-1, days=day) start_datetime = target_date + misc.get_class_start_time(time_pnt) end_datetime = target_date + misc.get_class_end_time(time_pnt) thisClass = icalendar.Event() thisClass["summary"] = each_class["name"] thisClass["location"] = each_class["classroom"] thisClass["dtend;TZID=Asia/Shanghai"] = end_datetime.strftime("%Y%m%dT%H%M%S") thisClass["dtstart;TZID=Asia/Shanghai"] = start_datetime.strftime("%Y%m%dT%H%M%S") thisClass["uid"] = \ start_datetime.strftime("%Y%m%dT%H%M%S") +\ "w" + str(week) +\ "@" + config.CrawlerParams.username ical.add_component(thisClass) except: pass # parse exam for each_exam in exam_lst: thisExamAlarm = icalendar.Alarm() thisExamAlarm["ACTION"] = "AUDIO" thisExamAlarm["TRIGGER"] = "-P1D" # remind 1 day earlier thisExamAlarm["ATTACH;VALUE"] = "URI:Chord" thisExamAlarm["UID"] = thisExamAlarm["X-WR-ALARMUID"] = \ each_exam["start"].strftime("%Y%m%dT%H%M%S") +\ "wexam_alarm@" + config.CrawlerParams.username thisExam = icalendar.Event() thisExam["summary"] = "【考试】" + each_exam["examname"] thisExam["location"] = each_exam["classroom"] thisExam["dtend;TZID=Asia/Shanghai"] = each_exam["end"].strftime("%Y%m%dT%H%M%S") thisExam["dtstart;TZID=Asia/Shanghai"] = each_exam["start"].strftime("%Y%m%dT%H%M%S") thisExam["UID"] = \ each_exam["start"].strftime("%Y%m%dT%H%M%S") +\ "wexam@" + config.CrawlerParams.username # thisExam.add_component(thisExamAlarm) ical.add_component(thisExam) if config.OutputTarget.stdout: print(ical.to_ical().decode('utf-8').replace('\r\n', '\n')) else: with open(config.OutputTarget.filePath, "wb") as fp: fp.write(ical.to_ical())
def generate(calendar, firstWeek): create_time = getCreateTime() with open("conf_classInfo.json", 'r') as f: data = json.load(f) classInfo = data["classInfo"] # 取出年、月、日 year = int(firstWeek[0:4]) month = int(firstWeek[4:6]) day = int(firstWeek[6:8]) print(len(classInfo)) for i in range(len(classInfo)): # 生成初始时间 first = datetime(year, month, day, 0, 0, 0) start = classInfo[i]["week"]["startWeek"] end = classInfo[i]["week"]["endWeek"] classTime = classInfo[i]["classTime"] weekday = classInfo[i]["weekday"] time = getClassTime(classTime) timeOfStart = time[0] timeOfEnd = time[1] for j in range(start - 1, end): print(j) startTime = first + timedelta(days=weekday + j * 7, hours=int(timeOfStart[0:2]), minutes=int(timeOfStart[2:4])) endTime = first + timedelta(days=weekday + j * 7, hours=int(timeOfEnd[0:2]), minutes=int(timeOfEnd[2:4])) print(startTime, endTime) summary = classInfo[i]["className"] + "@" + classInfo[i][ "classRoom"] # 创建事件 uid = getUID() event = icalendar.Event() event['uid'] = uid event.add("CREATE", create_time) event.add("SUMMARY", summary) event.add("TRANSP", "OPAQUE") event.add("X-APPLE-TRAVEL-ADVISORY-BEHAVIOR", "AUTOMATIC") event.add('DTSTART', startTime) event.add('DTEND', endTime) event['DTSTAMP'] = create_time event.add("SEQUENCE", "0") # 创建ALARM alarmUID = getAlarmUID() alarm = icalendar.Alarm() alarm.add("X-WR-ALARMUID", alarmUID) alarm["TRIGGER"] = "-PT30M" alarm.add("DESCRIPTION", "事件提醒") alarm.add("ACTION", "DISPLAY") alarm.add("UID", "VfKKDbniQ8&[email protected]") event.add_component(alarm) calendar.add_component(event) pass pass return calendar pass
def serialize_collaboration_alarm(fossil, now): alarm = ical.Alarm() trigger = timedelta(minutes=-int(fossil['alarm'])) alarm.set('trigger', trigger) alarm.set('action', 'DISPLAY') alarm.set('summary', VideoExportUtilities.getCondensedPrefix(fossil['type'], fossil['status']) + fossil['title'].decode('utf-8')) alarm.set('description', str(fossil['url'])) return alarm
def generate_calendar(classes): cal = icalendar.Calendar() cal.add('prodid', '-//WPI Calender Generator//adamgoldsmith.name//') cal.add('version', '2.0') tz = create_eastern_vtimezone() cal.add_component(tz) for index, c in enumerate(classes): event = icalendar.Event() if c['times'] == ['TBA']: continue # push the start and end dates back one day, then exclude the start date # this fixes a problem where the first day of the term would have all of the classes start_date = format_dates(c['dates'][0], c['times'][0]) - timedelta(days=1) # start of the first class end_date = format_dates(c['dates'][0], c['times'][1]) - timedelta(days=1) # end of the first class final_end_date = format_dates(c["dates"][1]) # end of the term event.add('summary', c['course'] + " " + c['type']) event.add('dtstart', start_date) event.add('location', c['location']) description = "{} {}\n{} {}".format(c['title'], c['section'], c['instructor'], c['instructor_email']) if c['Status'].split(' ')[0] == 'Waitlist': description += "\nWaitlist:" + c['waitlist_position'] event.add('description', description) event.add('dtend', end_date) event.add('rrule', {'freq': "weekly", 'until': final_end_date, 'byday': format_days(c['days'])}) event.add('exdate', start_date) event.add('uid', "WPICal_{}{}{}{}{}@adamgoldsmith.name".format(c['term'], c['course'], c['section'], c['type'], c['days']).replace(' ', '')) event.add('dtstamp', datetime.now()) if c['instructor_email'] is not None: organizer = icalendar.vCalAddress(c['instructor_email']) organizer.params['cn'] = c['instructor'] event['organizer'] = organizer alarm = icalendar.Alarm() alarm.add('trigger', icalendar.vDuration(timedelta(minutes=-10))) alarm.add('action', "display") event.add_component(alarm) cal.add_component(event) return cal
def add_ical_events(foirequest, cal): event_timezone = pytz.timezone(settings.TIME_ZONE) def tz(x): return x.astimezone(event_timezone) uid = 'event-%s-{pk}@{domain}'.format( pk=foirequest.id, domain=settings.SITE_URL.split('/')[-1]) title = '{} [#{}]'.format(foirequest.title, foirequest.pk) url = settings.SITE_URL + foirequest.get_absolute_url() event = icalendar.Event() event.add('uid', uid % 'request') event.add('dtstamp', tz(timezone.now())) event.add('dtstart', tz(foirequest.first_message)) event.add('url', url) event.add('summary', title) event.add('description', foirequest.description) cal.add_component(event) if foirequest.due_date: event = icalendar.Event() event.add('uid', uid % 'duedate') event.add('dtstamp', tz(timezone.now())) event.add('dtstart', tz(foirequest.due_date).date()) event.add('url', url) event.add('summary', _('Due date: %s') % title) event.add('description', foirequest.description) cal.add_component(event) if foirequest.status == 'awaiting_response' and ( foirequest.resolution in ('partially_successful', 'refused')): responses = foirequest.response_messages() if responses: appeal_deadline = foirequest.law.calculate_due_date( date=responses[-1].timestamp ) event = icalendar.Event() event.add('uid', uid % 'appeal_deadline') event.add('dtstamp', tz(timezone.now())) event.add('dtstart', tz(appeal_deadline).date()) event.add('url', url) event.add('summary', _('Appeal deadline: %s') % title) event.add('description', foirequest.description) alarm = icalendar.Alarm() alarm.add('trigger', icalendar.prop.vDuration(-timedelta(days=1))) alarm.add('action', 'DISPLAY') alarm.add('description', _('Appeal deadline: %s') % title) event.add_component(alarm) cal.add_component(event)
def bilibili(bilibili_config: Bilibili): uid_list = {} calendar = icalendar.Calendar() calendar.update() with open('./ics/bilibili.ics', 'rb') as file: c = icalendar.Calendar.from_ical(file.read()) for component in c.walk(): if component.name == "VEVENT": if datetime.now(tz=cst_tz) - component.get('dtstart').dt < timedelta(days=14): uid_list[(str(component.get('uid')))] = component calendar.add_component(component) timeline = get_timeline() for i in range(math.ceil(bilibili_config.limit / 30)): limit = 30 # 最后一页 if i + 1 == math.ceil(bilibili_config.limit / 30): limit = bilibili_config.limit - i * 30 bangumis = requests.get( f'https://api.bilibili.com/x/space/bangumi/follow/list?type=1&pn={i + 1}&ps={limit}&vmid={bilibili_config.uid}').json() for bangumi in bangumis['data']['list']: # 非连载番剧 if timeline.get(bangumi['season_id'], -1) == -1: continue title = f'{bangumi["title"]} {timeline[bangumi["season_id"]]["index"]}' uid = str(uuid.uuid5(uuid.NAMESPACE_OID, title)) + '@Dreace' datetime_start = datetime.fromtimestamp(timeline[bangumi['season_id']]['time'], cst_tz) datetime_end = datetime_start + relativedelta(minutes=30) event: icalendar.Event = uid_list.get(uid, None) if event: del event['dtstart'] del event['dtend'] event.add('dtstart', datetime_start) event.add('dtend', datetime_end) else: event = icalendar.Event() event.add('X-WR-TIMEZONE', 'Asia/Shanghai') event.add('uid', uid) event.add('summary', title) event.add('dtstart', datetime_start) event.add('dtend', datetime_end) event.add('TRIGGER', timedelta(minutes=-10)) # 开播十分钟前提醒 alarm = icalendar.Alarm() alarm.add("TRIGGER", timedelta(minutes=-10)) alarm.add("ACTION", "DISPLAY") event.add_component(alarm) calendar.add_component(event) with open('./ics/bilibili.ics', 'wb') as ics_file: # 去掉换行 ics_file.write(calendar.to_ical().replace('\r\n '.encode(), b''))
def alarm(self, before_minutes: int): alarm = icalendar.Alarm() alarm.add('UID', str(uuid.uuid3( uuid.NAMESPACE_DNS, str(self["summary"]) + str(uuid.uuid4()) + str(before_minutes) ))) alarm.add('ACTION', 'DISPLAY') alarm['TRIGGER'] = f'-PT{before_minutes}M' alarm.add('DESCRIPTION', '提醒事项') self.add_component(alarm) return self
def update_alarms(self, alarms): """ Replaces all alarms in the event that can be handled with the ones provided. """ components = self._vevents[self.ref].subcomponents # remove all alarms that we can handle from the subcomponents components = [c for c in components if not (c.name == 'VALARM' and self._can_handle_alarm(c))] # add all alarms we could handle from the input for alarm in alarms: new = icalendar.Alarm() new.add('ACTION', 'DISPLAY') new.add('TRIGGER', alarm[0]) new.add('DESCRIPTION', alarm[1]) components.append(new) self._vevents[self.ref].subcomponents = components
def addEvent(self, subject, starttime, endtime, place, uid, desc="", beforealert=0): """ addEvent(self, subject, starttime, endtime, place, uid, desc="", beforealert=0): """ # 添加Event event = icalendar.Event() event.add('CREATED', datetime.now()) event.add('LAST-MODIFIED', datetime.now()) event.add('DESCRIPTION', desc) event.add('DTEND', endtime) event.add('DTSTAMP', starttime) event.add('DTSTART', starttime) event.add('LOCATION', place) event.add('PRIORITY', '5') event.add('SUMMARY', subject) event.add('UID', uid) # 添加Alarm if beforealert != -1: alarm = icalendar.Alarm() alarm.add('TRIGGER', timedelta(seconds=-60 * beforealert)) alarm.add('ACTION', 'DISPLAY') alarm.add('DESCRIPTION', 'Reminder') event.add_component(alarm) self.cal.add_component(event)
import icalendar as ical from datetime import datetime, timedelta cal = ical.Calendar() cal.add('prodid', 'foo') cal.add('version', '2.0') for day_str in pack_lunches.keys(): start = parser.parse(day_str)[0] dtstart = datetime(start[0], start[1], start[2]).date() dtend = dtstart + timedelta(days = 1) trigger = datetime(start[0], start[1], start[2], 7, 0) summary = 'Pack lunch for %s' % " & ".join(pack_lunches[day_str]) event = ical.Event() event.add('summary', summary) event.add('dtstart', dtstart) event.add('dtend', dtend) alarm = ical.Alarm() alarm.add('trigger', trigger) alarm.add('action', 'DISPLAY') event.add_component(alarm) cal.add_component(event) import os filename = "/Users/dan/Desktop/Lunch %s.ics" % datetime.now().date() print filename f = open(filename, 'wb') f.write(cal.to_ical()) f.close()
def construct_calendar(courses, configs): # begin to construct event calendar = icalendar.Calendar() calendar.add('prodid', '-StephanXu Calendar-mrxzh.com-') calendar.add('version', '2.0') calendar.add('X-WR-CALNAME', configs['calendarConfig']['name']) max_week = 0 for course in courses: basic_time = datetime.datetime.strptime( configs['weekConfig']['first_week'], '%Y-%m-%d') + datetime.timedelta( days=myutil._get_wkday_offset(course['wkday'])) for week in course['week']: if week > max_week: max_week = week current_day = basic_time + datetime.timedelta( days=(int(week) - 1) * 7) start_time_off = datetime.datetime.strptime( myutil._get_start_time(configs['classTimes'], course['time']), '%H:%M').timetuple() end_time_off = datetime.datetime.strptime( myutil._get_end_time(configs['classTimes'], course['time']), '%H:%M').timetuple() start_time = current_day + \ datetime.timedelta(hours=start_time_off.tm_hour, minutes=start_time_off.tm_min) end_time = current_day + \ datetime.timedelta(hours=end_time_off.tm_hour, minutes=end_time_off.tm_min) base_timezone = pytz.timezone( configs['calendarConfig']['timezone']) start_time = base_timezone.localize(start_time) # start_time = start_time.astimezone( # pytz.timezone(configs['calendarConfig']['timezone'])) end_time = base_timezone.localize(end_time) # end_time = end_time.astimezone(pytz.timezone( # configs['calendarConfig']['timezone'])) event = icalendar.Event() event.add('summary', course['name']) event.add('uid', uuid.uuid4()) event.add('dtstart', start_time) event.add('dtend', end_time) event.add('dtstamp', start_time) if len(course['pos']) > 1: event.add('location', course['pos']) if len(course['more']) > 1: event.add('description', '%s' % (course['more'])) # set alarm if 'alarm' in configs['calendarConfig']: if 0 < eval(str(configs['calendarConfig']['alarm'])): alarm = icalendar.Alarm() alarm.add('action', 'DISPLAY') alarm.add('discription', 'Class reminder') alarm.add( 'trigger', datetime.timedelta( minutes=0 - eval(str(configs['calendarConfig']['alarm'])))) event.add_component(alarm) calendar.add_component(event) for week in range(0, max_week): week_mark_date = datetime.datetime.strptime( configs['weekConfig']['first_week'], '%Y-%m-%d') + datetime.timedelta(days=int(week) * 7) event = icalendar.Event() event.add('summary', '第{0}周'.format(week + 1)) event.add('uid', uuid.uuid4()) event.add('dtstart', week_mark_date) event.add('dtend', week_mark_date) calendar.add_component(event) pass return calendar.to_ical()
def __init__(self, organizer_email, start, summary, organizer_cn=None, description=None, duration='1h', location=None): """ :param str organizer_email: The email of the event organizer. :param start: The start time for the event. :type start: :py:class:`datetime.datetime` :param str summary: A short summary of the event. :param str organizer_cn: The name of the event organizer. :param str description: A more complete description of the event than what is provided by the *summary* parameter. :param duration: The events scheduled duration. :type duration: int, str, :py:class:`~datetime.timedelta`, :py:class:`.DurationAllDay` :param str location: The location for the event. """ utilities.assert_arg_type(start, datetime.datetime, 2) super(Calendar, self).__init__() if start.tzinfo is None: start = start.replace(tzinfo=dateutil.tz.tzlocal()) start = start.astimezone(dateutil.tz.tzutc()) for case in utilities.switch(duration, comp=isinstance): if case(str): duration = smoke_zephyr.utilities.parse_timespan(duration) duration = datetime.timedelta(seconds=duration) break if case(int): duration = datetime.timedelta(seconds=duration) break if case(datetime.timedelta): break if case(DurationAllDay): break else: raise TypeError('unknown duration type') self.add('method', 'REQUEST') self.add('prodid', 'Microsoft Exchange Server 2010') self.add('version', '2.0') self._event = icalendar.Event() event = self._event self.add_component(event) self.add_component(Timezone()) organizer = icalendar.vCalAddress('MAILTO:' + organizer_email) organizer.params['cn'] = icalendar.vText(organizer_cn or organizer_email) event['organizer'] = organizer event.add('description', description or summary) event.add('uid', str(uuid.uuid4())) event.add('summary', summary) if isinstance(duration, DurationAllDay): event.add('dtstart', start.date()) event.add('dtend', (start + datetime.timedelta(days=duration.days)).date()) else: event.add('dtstart', start) event.add('dtend', start + duration) event.add('class', 'PUBLIC') event.add('priority', 5) event.add('dtstamp', datetime.datetime.now(dateutil.tz.tzutc())) event.add('transp', 'OPAQUE') event.add('status', 'CONFIRMED') event.add('sequence', 0) if location: event.add('location', icalendar.vText(location)) alarm = icalendar.Alarm() alarm.add('description', 'REMINDER') alarm.add('trigger;related=start', '-PT1H') alarm.add('action', 'DISPLAY') event.add_component(alarm)
def sendAppointment(attendees, dtstart): #Login to SMTP server s = smtplib.SMTP('smtp.office365.com', 587) s.connect("smtp.office365.com", 587) s.ehlo() s.starttls() s.ehlo() username, password = prompt_creds() try: s.login(username, password) except smtplib.SMTPAuthenticationError: print("Invalid credentials. Please try again.") quit() # Timezone to use for our dates - change as needed tz = pytz.timezone("US/Eastern") reminderHours = 1 description = "wash dishes" start = tz.localize(dtstart) cal = icalendar.Calendar() cal.add('prodid', '-//My calendar application//example.com//') cal.add('version', '2.0') cal.add('method', "REQUEST") event = icalendar.Event() for attendee in attendees: event.add('attendee', attendee) event.add('organizer', username) event.add('status', "confirmed") event.add('category', "Event") event.add('summary', "wash n wait") event.add('description', description) event.add('location', "SigEp Kitchen") event.add('dtstart', start) event.add('dtend', start + dt.timedelta(hours=1)) event.add('dtstamp', tz.localize(dt.datetime.now())) event['uid'] = getUniqueId() # Generate some unique ID event.add('priority', 5) event.add('sequence', 1) event.add('created', tz.localize(dt.datetime.now())) alarm = icalendar.Alarm() alarm.add("action", "DISPLAY") alarm.add('description', "Reminder") alarm.add("trigger", dt.timedelta(hours=-reminderHours)) # The only way to convince Outlook to do it correctly alarm.add("TRIGGER;RELATED=START", "-PT{0}H".format(reminderHours)) event.add_component(alarm) cal.add_component(event) msg = MIMEMultipart("alternative") msg["Subject"] = "Wash 'n' Wait" msg["From"] = username msg['To'] = " ".join(attendees) msg["Content-class"] = "urn:content-classes:calendarmessage" msg.attach(MIMEText(description)) filename = "invite.ics" part = MIMEBase('text', "calendar", method="REQUEST", name=filename) part.set_payload( cal.to_ical() ) encode_base64(part) part.add_header('Content-Description', filename) part.add_header("Content-class", "urn:content-classes:calendarmessage") part.add_header("Filename", filename) part.add_header("Path", filename) msg.attach(part) send = input("Are you sure you want to send invitations? (type \"yes\" to send) ") if send.lower() != "yes": quit() try: s.sendmail(msg["From"], msg["To"], msg.as_string()) # print("would send mail HERE") except smtplib.SMTPDataError: print("SMTP failed to send the invite. SMTPDataError Thrown. You cannot send a calendar invite to the account you have logged in with.") except Exception as e: print("SMTP failed to send the invite:", e) else: print("Outlook invitation successfully sent to", msg['To']) s.quit()
def send_notify_email(body, start_time, title, attendees, event_uid, patching_duartion_in_min): """Function for send Outlook-notifications and save notification to disk""" subject = 'Linux Monthly Patching {month} | RFC {rfc_number} | {project}'.format( month=datetime.datetime.now().strftime("%B %Y"), rfc_number=rfc_number, project=title) start_time_utc=return_utc(start_time) # create calendar cal = icalendar.Calendar() cal.add('prodid', '-//My calendar application//example.com//') cal.add('version', '2.0') cal.add('method', 'REQUEST') # create event event = icalendar.Event() event.add('summary', subject) event.add('dtstart', datetime.datetime.strptime(start_time_utc, "%d-%m-%Y %H:%M")) event.add('dtend', datetime.datetime.strptime(start_time_utc, "%d-%m-%Y %H:%M")+datetime.timedelta(minutes=patching_duartion_in_min)) event.add('dtstamp', datetime.datetime.now().utcnow()) event['uid'] = event_uid event.add('TZOFFSETFROM', datetime.timedelta(hours=3)) event.add('TZOFFSETTO', datetime.timedelta(hours=3)) event.add('TZID', 'Russian Standard Time') event.add('priority', 5) event.add('organizer', settings['organizer']) event.add('status', "confirmed") event.add('category', "Event") event.add('sequence', 1) event.add('X-MICROSOFT-DISALLOW-COUNTER', "TRUE") event.add('X-MICROSOFT-CDO-BUSYSTATUS', 'FREE') for current_attendee in attendees.split(","): event.add('attendee', current_attendee) # create alarm alarm = icalendar.Alarm() alarm.add("action", "DISPLAY") alarm.add('description', "Reminder") alarm.add("TRIGGER;RELATED=START", "-PT15M") alarm.add('X-MICROSOFT-CDO-BUSYSTATUS', 'FREE') event.add_component(alarm) cal.add_component(event) filename = "invite.ics" msg = MIMEMultipart("mixed") msg["Subject"] = subject msg["From"] = settings['e_mail_from'] msg["To"] = attendees msg_for_cancel = copy.deepcopy(msg) cursor_hashes_db.execute('INSERT INTO "HASHES" (HASH,EMAILS) VALUES (?,?)', (str(event_uid), attendees)) connect_hashes_db.commit() msg_a = MIMEMultipart('alternative') msg.attach(msg_a) part_calendar = MIMEMultipart('text', "calendar", method="REQUEST", name=filename) part_calendar.set_type('text/calendar; charset=UTF-8; method=REQUEST; component = VEVENT') part_calendar.add_header('Content-Type', 'text/calendar') part_calendar.add_header('charset', 'UTF-8') part_calendar.add_header('component', 'VEVENT') part_calendar.add_header('method', 'REQUEST') part_calendar.add_header('Content-Description', filename) part_calendar.add_header('Content-ID', 'calendar_message') part_calendar.add_header("Content-class", "urn:content-classes:appointment") part_calendar.add_header("Filename", filename) part_calendar.add_header("Path", filename) part_calendar_before_encode=copy.deepcopy(part_calendar) part_calendar.set_payload(cal.to_ical()) encode_base64(part_calendar) msg_a.attach(MIMEText(body, 'html')) msg_a.attach(part_calendar) recept_list=attendees.split(",") try: s = smtplib.SMTP(settings['smtp_server']) s.sendmail(msg["From"], recept_list, msg.as_string()) s.quit() print("e-mail with '{title}' title has been sent successfully!".format(title=title)) except Exception as e: termcolor.cprint("Error during sending an-email, second try...", color="white", on_color="on_red") try: s = smtplib.SMTP(settings['smtp_server']) print(recept_list) s.sendmail(msg["From"], recept_list, msg.as_string()) s.quit() print("e-mail with '{title}' title has been sent successfully!".format(title=title)) except Exception as e: termcolor.cprint("Can not send outlook-notofocation for this {prj} project to {start_date}".format(start_date=start_time, prj=title), color="white", on_color="on_red") print("Exception: {e}".format(e=str(e))) cal.update({'method' : 'CANCEL'}) event.update({'summary' : "[CANCELLED] " + subject}) event.update({'status': "cancelled"}) msg_for_cancel.replace_header('Subject', "[CANCELLED] " + subject) msg_a_for_cancel = MIMEMultipart('alternative') msg_for_cancel.attach(msg_a_for_cancel) msg_a_for_cancel.attach(MIMEText(body.replace("please, perform this patching", "<font size=12 color='red'>DO NOT DO IT</font>"), 'html')) part_calendar_before_encode.replace_header('Content-Type', 'text/calendar; charset="UTF-8"; method="CANCEL"; component = "VEVENT"; name="invite.ics"; boundary="calendar"') part_calendar_before_encode.replace_header('method', 'CANCEL') part_calendar_before_encode.set_payload(cal.to_ical()) encode_base64(part_calendar_before_encode) msg_a_for_cancel.attach(part_calendar_before_encode) save_notification_to_disk=open("./archive/" + event_uid + ".msg", 'wb') save_notification_to_disk.write(msg_for_cancel.as_bytes()) save_notification_to_disk.close() input("Enter any symbol to proceed...")
async def send_meeting_invite(params: Details): subj = params.subject start_hour = int(params.start_hour) start_minute = int(params.start_min) start_day = int(params.day) start_month = int(params.month) start_year = int(params.year) attendee_email = params.attendees start_date = dt.datetime(start_year, start_month, start_day) # return start_date organiser_email = 'from mail id' time_now = datetime.now() description = 'join the event created for you on' + str(time_now) reminder_hours = 15 tz = pytz.timezone("Asia/Calcutta") # Build the event itself cal = icalendar.Calendar() cal.add('PRODID', '-//Microsoft Corporation//Outlook MIMEDIR//EN') cal.add('VERSION', '2.0') event = icalendar.Event() # event.add( # "ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN={0}".format(attendee_email), # "mailto:{0}".format(attendee_email)) only for having the option to accept the meeting with the pop up. event.add("ATTENDEE", attendee_email) # comment if you want to have the above line. event.add("organizer;CN={0}".format(organiser_email), "mailto:{0}".format(organiser_email)) event.add('summary', subj) event.add('category', "EVENT") event.add('description', description) event.add('location', 'India') event.add( 'dtstart', tz.localize( dt.datetime.combine(start_date, dt.time(start_hour, start_minute, 0)))) event.add( 'dtend', tz.localize( dt.datetime.combine(start_date, dt.time(start_hour + 1, start_minute, 0)))) event.add( 'dtstamp', tz.localize( dt.datetime.combine(start_date, dt.time(start_hour, start_minute, 0)))) event.add('priority', 3) event['uid'] = uuid.uuid1() # Generate some unique ID event.add('sequence', 0) event.add('status', "CONFIRMED") event.add('TRANSP', 'OPAQUE') # custom set up alarm alarm = icalendar.Alarm() alarm.add('description', "Reminder") # The only way to convince Outlook to do it correctly alarm.add("TRIGGER;RELATED=START", "-PT{0}M".format(reminder_hours)) alarm.add("ACTION", "DISPLAY") event.add_component(alarm) cal.add_component(event) # generate the ics file filename = "invitedev.ics" part = MIMEBase('text', 'calendar', method='REQUEST', name=filename, component="VEVENT") part.set_payload(cal.to_ical()) encode_base64(part) # part.add_header('Content-Disposition', 'attachment; filename={0}'.format(filename)) part.add_header('Content-Description', filename) part.add_header('Content-class', "urn:content-classes:calendarmessage") part.add_header('Filename', filename) part.add_header('Path', filename) # print("Part : \n",part) # send the mail mailer = PostmarkClient(server_token='-----server token ---------') mailer.emails.send(From=organiser_email, To=attendee_email, Subject=subj, HtmlBody=description, Attachments=[part]) return event
def __alarm(self): alarm = icalendar.Alarm() alarm.add('action', 'DISPLAY') alarm.add('trigger', timedelta(minutes=-30)) return alarm