Problem with setting calendar recurrence

I am unable to correctly set the calendar recurrence .
my code →
MapiCalendar appointment = new MapiCalendar();
const long PR_MEETING_STATUS = 0x82170003;

appointment.SetProperty(new MapiProperty(PR_MEETING_STATUS,
BitConverter.GetBytes(1) /* 1 = meeting*/));

string sub = “”;
if (!string.IsNullOrEmpty(appointmentFields.Subject1))
{
appointment.Subject = appointmentFields.Subject1;
}
appointment.Recurrence = new MapiCalendarEventRecurrence();

if (!string.IsNullOrEmpty(appointmentFields.Recurrence_StartDate))
{
appointment.Recurrence.RecurrencePattern.StartDate = DateTime.ParseExact(appointmentFields.Recurrence_StartDate, “ddd, dd MMM yyyy HH:mm:ss”, CultureInfo.InvariantCulture);
}
if (!string.IsNullOrEmpty(appointmentFields.Recurrence_EndDate))
{
//appointment.Recurrence.RecurrencePattern.EndDate = DateTime.FromOADate(double.Parse(appointmentFields.Recurrence_EndDate));
appointment.Recurrence.RecurrencePattern.EndDate = DateTime.ParseExact(appointmentFields.Recurrence_EndDate, “ddd, dd MMM yyyy HH:mm:ss”, CultureInfo.InvariantCulture);
}
if (!string.IsNullOrEmpty(appointmentFields.Recurrence_PatternType))
{
appointment.Recurrence.RecurrencePattern.PatternType = (Aspose.Email.Mapi.MapiCalendarRecurrencePatternType)ConvertStringToInt(appointmentFields.Recurrence_PatternType);
}
if (!string.IsNullOrEmpty(appointmentFields.Recurrence_EndType))
{
appointment.Recurrence.RecurrencePattern.EndType = (Aspose.Email.Mapi.MapiCalendarRecurrenceEndType)ConvertStringToInt(appointmentFields.Recurrence_EndType);
}
if (!string.IsNullOrEmpty(appointmentFields.NumberOfOccurrences))
{
appointment.Recurrence.RecurrencePattern.OccurrenceCount = (uint)ConvertStringToInt(appointmentFields.NumberOfOccurrences);
}
if (!string.IsNullOrEmpty(appointmentFields.Recurrence_WeekStartDay))
{
appointment.Recurrence.RecurrencePattern.WeekStartDay = (System.DayOfWeek)ConvertStringToInt(appointmentFields.Recurrence_WeekStartDay);
}
also there is no option to set calendar recurrence type yearly.
please help me with detailed documentation with code to understand and set calendar recurrence and then save it to pst.

Hello @kumarpiyush01,

There are a few issues in your code.

1. NullReferenceException

new MapiCalendarEventRecurrence() leaves RecurrencePattern set to null.
MapiCalendarRecurrencePattern is an abstract base class, so you have to
assign a concrete pattern object yourself:

  • MapiCalendarDailyRecurrencePattern — Period in days
  • MapiCalendarWeeklyRecurrencePattern — Period in weeks, plus DayOfWeek
  • MapiCalendarMonthlyRecurrencePattern — Period in months, plus Day
  • MapiCalendarMonthlyNthRecurrencePattern — Period in months, plus DayOfWeek + Position

2. There is no “Yearly” pattern type — and none is needed

This follows the MS-OXOCAL specification: a yearly series is a monthly
pattern with Period = 12 (24 for every two years, etc.). Frequency is a
read-only computed property — Aspose.Email sets it to Yearly automatically:

Yearly Jan 15 -> Frequency=Yearly, PatternType=Month, Period=12
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTHDAY=15;BYMONTH=1

3. MapiCalendarRecurrenceEndType values are not 0/1/2

EndAfterDate = 8225, EndAfterNOccurrences = 8226, NeverEnd = 8227.
Your (MapiCalendarRecurrenceEndType)ConvertStringToInt(...) cast will
silently produce None if the source string holds a small index, and the
recurrence will not be written. Please map the values explicitly.

4. StartDate is mandatory

If RecurrencePattern.StartDate is left at DateTime.MinValue, the whole
recurrence is silently dropped on save.

5. Do not set PidLidAppointmentStateFlags by a hardcoded tag

0x82170003 is a named property; its numeric id is assigned dynamically by
the store, so a hardcoded tag is not reliable. Use the descriptor instead:

appointment.SetProperty(KnownPropertyList.AppointmentStateFlags,
                        (int)MapiCalendarState.Meeting);

Complete working example — all pattern types + saving to PST:

using Aspose.Email.Calendar.Recurrences;
using Aspose.Email.Mapi;
using Aspose.Email.Storage.Pst;

static MapiCalendar NewAppointment(string subject)
{
    var appt = new MapiCalendar(
        "Room 1", subject, "body",
        new DateTime(2026, 1, 15, 10, 0, 0),
        new DateTime(2026, 1, 15, 11, 0, 0));

    appt.SetProperty(KnownPropertyList.AppointmentStateFlags,
                     (int)MapiCalendarState.Meeting);
    return appt;
}

// --- DAILY: every 2 days, 10 occurrences ---
var daily = NewAppointment("Daily every 2 days");
daily.Recurrence = new MapiCalendarEventRecurrence
{
    RecurrencePattern = new MapiCalendarDailyRecurrencePattern
    {
        PatternType     = MapiCalendarRecurrencePatternType.Day,
        Period          = 2,                       // days
        StartDate       = new DateTime(2026, 1, 15),
        EndType         = MapiCalendarRecurrenceEndType.EndAfterNOccurrences,
        OccurrenceCount = 10
    }
};

// --- WEEKLY: every Mon and Wed until 30 Jun 2026 ---
var weekly = NewAppointment("Weekly Mon/Wed");
weekly.Recurrence = new MapiCalendarEventRecurrence
{
    RecurrencePattern = new MapiCalendarWeeklyRecurrencePattern
    {
        PatternType  = MapiCalendarRecurrencePatternType.Week,
        Period       = 1,                          // weeks
        DayOfWeek    = MapiCalendarDayOfWeek.Monday | MapiCalendarDayOfWeek.Wednesday,
        StartDate    = new DateTime(2026, 1, 12),
        EndType      = MapiCalendarRecurrenceEndType.EndAfterDate,
        EndDate      = new DateTime(2026, 6, 30),
        WeekStartDay = DayOfWeek.Monday
    }
};

// --- MONTHLY: the 15th of every month, no end ---
var monthly = NewAppointment("Monthly day 15");
monthly.Recurrence = new MapiCalendarEventRecurrence
{
    RecurrencePattern = new MapiCalendarMonthlyRecurrencePattern
    {
        PatternType = MapiCalendarRecurrencePatternType.Month,
        Period      = 1,                           // months
        Day         = 15,
        StartDate   = new DateTime(2026, 1, 15),
        EndType     = MapiCalendarRecurrenceEndType.NeverEnd
    }
};

// --- MONTHLY Nth: 2nd Tuesday of every month, 12 occurrences ---
var monthlyNth = NewAppointment("Monthly 2nd Tuesday");
monthlyNth.Recurrence = new MapiCalendarEventRecurrence
{
    RecurrencePattern = new MapiCalendarMonthlyNthRecurrencePattern
    {
        PatternType     = MapiCalendarRecurrencePatternType.MonthNth,
        Period          = 1,
        DayOfWeek       = MapiCalendarDayOfWeek.Tuesday,
        Position        = DayPosition.Second,
        StartDate       = new DateTime(2026, 1, 13),
        EndType         = MapiCalendarRecurrenceEndType.EndAfterNOccurrences,
        OccurrenceCount = 12
    }
};

// --- YEARLY: every 15 January, no end   (Period = 12 months) ---
var yearly = NewAppointment("Yearly Jan 15");
yearly.Recurrence = new MapiCalendarEventRecurrence
{
    RecurrencePattern = new MapiCalendarMonthlyRecurrencePattern
    {
        PatternType = MapiCalendarRecurrencePatternType.Month,
        Period      = 12,                          // 12 months == yearly
        Day         = 15,
        StartDate   = new DateTime(2026, 1, 15),
        EndType     = MapiCalendarRecurrenceEndType.NeverEnd
    }
};

// --- YEARLY Nth: 3rd Friday of November, 5 occurrences ---
var yearlyNth = NewAppointment("Yearly 3rd Fri of Nov");
yearlyNth.Recurrence = new MapiCalendarEventRecurrence
{
    RecurrencePattern = new MapiCalendarMonthlyNthRecurrencePattern
    {
        PatternType     = MapiCalendarRecurrencePatternType.MonthNth,
        Period          = 12,
        DayOfWeek       = MapiCalendarDayOfWeek.Friday,
        Position        = DayPosition.Third,
        StartDate       = new DateTime(2026, 11, 20),
        EndType         = MapiCalendarRecurrenceEndType.EndAfterNOccurrences,
        OccurrenceCount = 5
    }
};

// --- save everything to a PST ---
using (var pst = PersonalStorage.Create("recurrences.pst", FileFormatVersion.Unicode))
{
    var calendar = pst.CreatePredefinedFolder("Calendar", StandardIpmFolder.Appointments);

    calendar.AddMapiMessageItem(daily);
    calendar.AddMapiMessageItem(weekly);
    calendar.AddMapiMessageItem(monthly);
    calendar.AddMapiMessageItem(monthlyNth);
    calendar.AddMapiMessageItem(yearly);
    calendar.AddMapiMessageItem(yearlyNth);
}

Optional: building a pattern from an iCalendar rule

MapiCalendarRecurrencePatternFactory.FromString accepts a full iCalendar
recurrence block — a bare FREQ=... string is not enough, DTSTART must be
present, and the resulting StartDate still has to be assigned manually:

var pattern = MapiCalendarRecurrencePatternFactory.FromString(
    "DTSTART:20260115T100000Z\r\nRRULE:FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=15;COUNT=5");
pattern.StartDate = new DateTime(2026, 1, 15);   // required

appointment.Recurrence = new MapiCalendarEventRecurrence { RecurrencePattern = pattern };

Documentation: Managing Recurrences|Documentation

Thank you.