Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error "Incorrect ics/ical URL" syncing an outlook calendar #388

Closed
konraddecker opened this issue Dec 11, 2023 · 11 comments
Closed

Error "Incorrect ics/ical URL" syncing an outlook calendar #388

konraddecker opened this issue Dec 11, 2023 · 11 comments

Comments

@konraddecker
Copy link

The problem

Unfortunately the sync stopped working for me recently.
The following error is displayed in the console (see Screenshot)
2023-12-11 08_40_32-

I have already recreated the Outlook calendar share and generated new links. Unfortunately it does not work.

is this bug known? Is there a fix for this?

Version of GAS-ICS-Sync

5.7

Additional information & file uploads

No response

@irqnet
Copy link

irqnet commented Dec 11, 2023

Same here, seems that fetching the ics url timed out, which leads into removal of all existing calendar entries.

Would it be possible to check whether the content is empty to give it a retry? Putting that URL into a browser to download the ics manually take a while, so I assume it's just a timeout issue.

function fetchSourceCalendars(sourceCalendarURLs){

@Kucladell
Copy link

I was experiencing the same issue separately, and was able to analyze the problem and come up with a solution. Please refer to the information below.

The underlying issue

Microsoft Outlook/365's calendar share is outputting ICS files that are incompliant to ICS standards. The specific issues that affect GAS-ICS-Sync are as follows:

  • The file is not marked with 'END:VCALENDAR' at the end.
  • Each event is marked with a 'BEGIN:VEVENT' at the start but is not marked with a 'END:VEVENT' at the end.

How to fix

This issue can be resolved by fixing the ICS file to comply to ICS standards before parsing.
Add the following changes in the Helpers.gs file:

  • Revise fetchSourceCalendars() function as shown below:
function fetchSourceCalendars(sourceCalendarURLs){
  var result = []
  for (var source of sourceCalendarURLs){
    var url = source[0].replace("webcal://", "https://");
    var colorId = source[1];
    
    callWithBackoff(function() {
      var urlResponse = UrlFetchApp.fetch(url, { 'validateHttpsCertificates' : false, 'muteHttpExceptions' : true });
      if (urlResponse.getResponseCode() == 200){
        var urlContent = RegExp("(BEGIN:VCALENDAR.*?END:VCALENDAR)", "s").exec(urlResponse.getContentText());
        
        // Attempt to fix ICS file if initial parse was unsuccessful
        if(urlContent == null){
          var urlContent = RegExp("(BEGIN:VCALENDAR.*?END:VCALENDAR)", "s").exec(fixICS(urlResponse.getContentText()));
        }

        if(urlContent == null){
          Logger.log("[ERROR] Incorrect ics/ical URL: " + url);
          return;
        }
        else{
          result.push([urlContent[0], colorId]);
          return;
        }     
      }
      else{ //Throw here to make callWithBackoff run again
        throw "Error: Encountered HTTP error " + urlResponse.getResponseCode() + " when accessing " + url; 
      }
    }, defaultMaxRetries);
  }
  
  return result;
}
  • Add a fixICS() function as shown below:
// Fix ICS file from Microsoft Outlook/365 that is incompliant to ICS standards
function fixICS(text) {
  // Split the text into lines
  const lines = text.split('\n');

  // Flag to track if a new event is encountered
  let veventSectionEntered = false;

  // Process lines in forward order
  for (let i = 0; i < lines.length; i++) {
    if (lines[i].startsWith('BEGIN:VEVENT')) {
      // Check if this is the first encounter of BEGIN:VEVENT
      if (!veventSectionEntered) {
        veventSectionEntered = true;
        continue;
      }
      // Skip if END:VEVENT is already added
      if (lines[i-1].startsWith('END:VEVENT')) {
        continue;
      }
      // Add `END:VEVENT` with a line break before the current `BEGIN:VEVENT`
      lines.splice(i, 0, 'END:VEVENT');
    }
  }

  // Check if `END:VCALENDAR` is missing and add it if necessary
  if (!lines[lines.length - 1].startsWith('END:VCALENDAR')) {
    lines.splice(lines.length - 1, 0, 'END:VCALENDAR');
  }

  // Join lines with line breaks
  return lines.join('\n');
}

Final thoughts

The code above is a very crude attempt to fix this issue; this does solve the sync issue, but please add a comment below if you have a more elegant solution.

It is unclear as to why this issue suddenly appeared. Did Microsoft Outlook/365 suddenly began writing ICS file incorrectly? Is there something wrong on the parser side? I would appreciate any details and discussions below.

@Kucladell
Copy link

Same here, seems that fetching the ics url timed out, which leads into removal of all existing calendar entries.

Would it be possible to check whether the content is empty to give it a retry? Putting that URL into a browser to download the ics manually take a while, so I assume it's just a timeout issue.

function fetchSourceCalendars(sourceCalendarURLs){

As for the issue of all existing calendar entries being removed, you may want to implement some changes in the code to prevent this from happenig. The issue below provides a solution you can use.
#343

@konraddecker
Copy link
Author

thanks, the fix worked.

Is this an Office365 error? Some calendars take longer to download the ics file?

@jonas0b1011001
Copy link
Collaborator

Is this an Office365 error

Yes, this is a bug in the latest Outlook version. See #386 for more.

@Kucladell Thanks for your solution, I have not had time to thoroughly test this, just 2 quick inputs:

  1. Your code will leave the last VEVENT component unfixed as it always fixes the component above the one you are currently looking at.
  2. END:VCALENDAR is added at the wrong position, splice basically adds the items before the index you provide. You have to either use lines.splice(lines.length , 0, 'END:VCALENDAR'); or just use lines.push('END:VCALENDAR');

@Kucladell
Copy link

Kucladell commented Dec 11, 2023

@konraddecker Glad to be able to help! Thank you as well for confirming that the fix indeed works.

@jonas0b1011001 Thank you for the detailed input! I am not well versed in Javascript (and programming in general) so I deeply appreciate your feedback. As for the points you raised:

  1. You are correct that the last VEVENT component will remain unfixed. I initially took this approach since Microsoft's flawed output file has a 'END:VEVENT' at the last VEVENT component. I will attempt to come up with a more thorough code that doesn't rely on a specific type of error.
  2. This is due to my incompetence; I initially used lines.push() but this ended up with a blank line before the last line, so I ended up with this botch. The current fix above works only because the parser reads from BEGIN:VCALENDAER to END:VCALENDAR and ignores anything that comes after. I will have another go at this.

(Edit: A better solution is proposed, so removed comments on improving my code.)

@Kucladell
Copy link

@jonas0b1011001 I see that you proposed a more elegant solution at #386 . I suggest you go ahead with this!

@jonas0b1011001 jonas0b1011001 changed the title Incorrect ics/icas URL Error "Incorrect ics/ical URL" syncing an outlook calendar Dec 11, 2023
@jonas0b1011001 jonas0b1011001 pinned this issue Dec 11, 2023
@arcegabriel
Copy link

Just logged in to say thanks for @Kucladell for the fix. It was driving me crazy

@Kucladell
Copy link

@arcegabriel Thank you for the kind words! A more elegant solution is coming up soon by @jonas0b1011001, but glad to be able to help in the meantime. This is the first time I shared my code to someone else so this means a lot to me.

@derekantrican
Copy link
Owner

Closing via #386 . Release with the fix coming shortly

@brenthaag
Copy link

My syncing started doing this sometime before I got up for the day, but by mid-morning it started working again! Not sure what microsoft is doing, but I'm very glad there may be a solution I should implement when it happens again.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants