python-caldav / caldav

Apache License 2.0
313 stars 91 forks source link

Server says "Forbidden" when creating event with timezone #372

Open seanmills1020 opened 6 months ago

seanmills1020 commented 6 months ago

Hello,

I am new to Python, so I feel like I am making a silly mistake.

I am trying to add an event to my calendar. The following code works:

from datetime import datetime
import caldav

with caldav.DAVClient(url=CALENDAR_SERVER_URL, username=USERNAME, password=PASSWORD,
                      ssl_verify_cert=False) as client:

    calendar = client.calendar(url=USER_CALENDAR_URL)
    timestamp_start = datetime(year=2024, month=1, day=26, hour=18, minute=0, second=0)
    timestamp_end = datetime(year=2024, month=1, day=26, hour=18, minute=30, second=0)

    new_event = calendar.save_event(
        dtstart=timestamp_start,
        dtend=timestamp_end,
        summary="Sean's Comedy Debut"
    )

However, if I add a tzinfo argument, I get an error.

from datetime import datetime
from dateutil import tz
import caldav

with caldav.DAVClient(url=CALENDAR_SERVER_URL, username=USERNAME, password=PASSWORD,
                      ssl_verify_cert=False) as client:

    calendar = client.calendar(url=USER_CALENDAR_URL)
    timezone = tz.gettz("America/Los_Angeles")
    timestamp_start = datetime(year=2024, month=1, day=26, hour=18, minute=0, second=0, tzinfo=timezone)
    timestamp_end = datetime(year=2024, month=1, day=26, hour=18, minute=30, second=0, tzinfo=timezone)

    new_event = calendar.save_event(
        dtstart=timestamp_start,
        dtend=timestamp_end,
        summary="Sean's Comedy Debut"
    )

The last part of the traceback is: caldav.lib.error.AuthorizationError: AuthorizationError at '<some_url>', reason Forbidden

Any ideas?

tobixen commented 6 months ago

Hmm ... what happens if you use zoneinfo.ZoneInfo('America/Los_Angeles') instead of tz.gettz("America/Los_Angeles")?

AuthorizationError is a bit misleading here, possibly the library transmits something the server deems to be invalid.

In the master branch (I'll try to find some time to make a new release soon) there is a debug hook, if you set the environment variable PYTHON_CALDAV_COMMDUMP then the library will dump some communication files under /tmp - would be useful to see if the library is shipping the timezone information correctly to the server. (Hm, actually I think I realized at some point that it's easier to just convert the time to UTC when creating events).

seanmills1020 commented 6 months ago

Switching to ZoneInfo worked! Thank you!

Here is the updated code:

from datetime import datetime
from zoneinfo import ZoneInfo
import caldav

with caldav.DAVClient(url=CALENDAR_SERVER_URL, username=USERNAME, password=PASSWORD,
                      ssl_verify_cert=False) as client:

    calendar = client.calendar(url=USER_CALENDAR_URL)
    timezone = ZoneInfo("America/Los_Angeles")
    timestamp_start = datetime(year=2024, month=1, day=26, hour=18, minute=0, second=0, tzinfo=timezone)
    timestamp_end = datetime(year=2024, month=1, day=26, hour=18, minute=30, second=0, tzinfo=timezone)

    new_event = calendar.save_event(
        dtstart=timestamp_start,
        dtend=timestamp_end,
        summary="Sean's Comedy Debut"
    )
tobixen commented 6 months ago

It's a bit weird. I should probably come back and look into this at some point.

tobixen commented 6 months ago

This is the gist of it, if I remember correctly:

I'm not sure what is the best way to handle this ... possibly it involves embedding the timezone data into the icalendar object. That's something the icalendar library should handle, in that case.

I leave this open as an issue - it needs better handling than today in any case.