+
+
+
+ <% date_range.each_slice(7) do |week| %>
+
+ <% week.each do |day| %>
+ <%= content_tag :td, class: calendar.td_classes_for(day) do %>
+ <% instance_exec(day, calendar.sorted_events_for(day), &passed_block) %>
+ <% end %>
+ <% end %>
+
+ <% end %>
+
+
+
diff --git a/config/routes.rb b/config/routes.rb
index 35bfaa18a..7a4c73cb4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -46,6 +46,10 @@ def self.matches?(request)
end
end
+ # calendar / meetings functionality
+ resources :calendars, controller: 'comfy/admin/calendars'
+ resources :meetings
+
resource :web_settings, controller: 'comfy/admin/web_settings', only: [:edit, :update]
resources :users, controller: 'comfy/admin/users', as: :admin_users, except: [:create, :show] do
collection do
diff --git a/db/migrate/20230913160600_create_meetings.rb b/db/migrate/20230913160600_create_meetings.rb
new file mode 100755
index 000000000..576eabebf
--- /dev/null
+++ b/db/migrate/20230913160600_create_meetings.rb
@@ -0,0 +1,19 @@
+class CreateMeetings < ActiveRecord::Migration[6.1]
+ def change
+ create_table :meetings do |t|
+ t.string :name
+ t.datetime :start_time, null: false
+ t.datetime :end_time, null: false
+ t.text :participant_emails, array: true, default: []
+ t.text :description
+ t.string :timezone, null: false
+ t.string :location
+ t.string :status, null: false
+ t.string :external_meeting_id, null: false
+ t.jsonb :custom_properties, default: '{}'
+
+ t.timestamps
+ end
+ add_index :meetings, :external_meeting_id, unique: true
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0fca04b3c..4c2e5e965 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2023_05_16_012035) do
+ActiveRecord::Schema.define(version: 2023_09_13_160600) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -429,6 +429,22 @@
t.datetime "updated_at", precision: 6, null: false
end
+ create_table "meetings", force: :cascade do |t|
+ t.string "name"
+ t.datetime "start_time", null: false
+ t.datetime "end_time", null: false
+ t.text "participant_emails", default: [], array: true
+ t.text "description"
+ t.string "timezone", null: false
+ t.string "location"
+ t.string "status", null: false
+ t.string "external_meeting_id", null: false
+ t.jsonb "custom_properties", default: "{}"
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ t.index ["external_meeting_id"], name: "index_meetings_on_external_meeting_id", unique: true
+ end
+
create_table "message_threads", force: :cascade do |t|
t.boolean "unread"
t.datetime "deleted_at"
diff --git a/test/controllers/meetings_controller_test.rb b/test/controllers/meetings_controller_test.rb
new file mode 100644
index 000000000..db6cd9b9a
--- /dev/null
+++ b/test/controllers/meetings_controller_test.rb
@@ -0,0 +1,51 @@
+require "test_helper"
+
+class MeetingsControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @meeting = meetings(:one)
+ @user = users(:public)
+ @user.update(can_manage_email: true)
+ sign_in(@user)
+ end
+
+ test "should get index" do
+ get meetings_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_meeting_url
+ assert_response :success
+ end
+
+ test "should create meeting" do
+ assert_difference('Meeting.count') do
+ post meetings_url, params: { meeting: { description: @meeting.description, end_time: @meeting.end_time, location: @meeting.location, name: @meeting.name, participant_emails: ['contact@restarone.com'], start_time: @meeting.start_time, status: @meeting.status, timezone: @meeting.timezone } }
+ end
+
+ assert_redirected_to meeting_url(Meeting.last)
+ end
+
+ test "should show meeting" do
+ get meeting_url(@meeting)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_meeting_url(@meeting)
+ assert_response :success
+ end
+
+ test "should update meeting" do
+ patch meeting_url(@meeting), params: { meeting: { description: @meeting.description, end_time: @meeting.end_time, location: @meeting.location, name: @meeting.name, participant_emails: @meeting.participant_emails, start_time: @meeting.start_time, status: "TENTATIVE", timezone: @meeting.timezone } }
+ assert_redirected_to meeting_url(@meeting)
+ end
+
+ test "should destroy meeting" do
+ assert_difference('Meeting.count', -1) do
+ delete meeting_url(@meeting)
+ end
+
+ assert_redirected_to meetings_url
+ end
+end
diff --git a/test/fixtures/files/email_with_calendar_invite.eml b/test/fixtures/files/email_with_calendar_invite.eml
new file mode 100644
index 000000000..1d8fb341d
--- /dev/null
+++ b/test/fixtures/files/email_with_calendar_invite.eml
@@ -0,0 +1,893 @@
+Delivered-To: restarone@restarone.solutions
+Received: by 2002:a9a:7443:0:b0:26d:f5c7:8136 with SMTP id m3csp3319080lkn;
+ Wed, 13 Sep 2023 06:47:41 -0700 (PDT)
+X-Received: by 2002:ad4:4446:0:b0:655:cf0f:6704 with SMTP id l6-20020ad44446000000b00655cf0f6704mr2657418qvt.5.1694612860430;
+ Wed, 13 Sep 2023 06:47:40 -0700 (PDT)
+ARC-Seal: i=1; a=rsa-sha256; t=1694612860; cv=none;
+ d=google.com; s=arc-20160816;
+ b=yajeqbL7Up6JLXkzQUXVPUt0dHRL+EDPmJ/naSDyOxG+WYTeWrgoy7QCoghbwmUl99
+ Y2FnsJoXXq7Igc/wxZhJz2u/BzDIhubb/0asmscO/98q9Dx6TeMNlBodtDyuMe99R711
+ esEWka1GaBhRHokPl7gqNn9wjhpqmGqndEpNvfDZ0Pps/iYllEsdMzX5FtndCjddtr+Q
+ ANQlvSmXBD+VS2xU3zTM0nWJmpgFNDZhF1a+WgubwyaL6qbduzoPaBZ13Vvc5vhrlzPH
+ PNXnG+Q+/7a9VI6pqYXHux4rcrrkyCUq4dgE8POXss2IeASvULVjNvPIHg0ZcGwIYgCT
+ y31w==
+ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
+ h=to:from:subject:date:message-id:sender:reply-to:mime-version
+ :dkim-signature:dkim-signature;
+ bh=jQjL48TRbWIpmFbKg7lGniGzhaf+TVo9+lJ67nhrZk4=;
+ fh=3YrH2AqvZR8DkO7aOt+6Qken8yFGbL96xDY6JnnMGNk=;
+ b=CGM8nMyhcs5B3t5Ha0O8sDCw0op+5YKXdxi3ooNSOcMPPFmg6KFQK5Hi+Cc4jDr8Y2
+ M9N2mqq4DCGjbxxQTGY1rsB6E1MpepXAMUX+qV/W0wKi/4WX1GBaxcRJgbxfSW1Gk6Q7
+ LDqcv7+lSAw1e+wP6syoPC/6z3xWq2NpcVUiscRHDiDzexn+nnwJE5BFutbWhzHip6yr
+ fWfDaskZMM/MUm5YG062ipqPWPaxsYD6KaJj8kfkcvRk6kPDIN6K78qc/Fr/wA2p6KR/
+ AGxrcL8tDL2kdyHvNcoFUZLEY+mM8ICKTks8L+DoWCCW+tku79npMgGFZLtem/jOQGPe
+ KhTA==
+ARC-Authentication-Results: i=1; mx.google.com;
+ dkim=pass header.i=@google.com header.s=20230601 header.b=4cb2kpAG;
+ dkim=pass header.i=@restarone.com header.s=google header.b=c9L85yhO;
+ spf=pass (google.com: domain of contact@restarone.com designates 209.85.220.73 as permitted sender) smtp.mailfrom=contact@restarone.com
+Return-Path:
+Received: from mail-sor-f73.google.com (mail-sor-f73.google.com. [209.85.220.73])
+ by mx.google.com with SMTPS id n6-20020a0c8c06000000b00631f654d349sor4820453qvb.5.2023.09.13.06.47.40
+ for
+ (Google Transport Security);
+ Wed, 13 Sep 2023 06:47:40 -0700 (PDT)
+Received-SPF: pass (google.com: domain of contact@restarone.com designates 209.85.220.73 as permitted sender) client-ip=209.85.220.73;
+Authentication-Results: mx.google.com;
+ dkim=pass header.i=@google.com header.s=20230601 header.b=4cb2kpAG;
+ dkim=pass header.i=@restarone.com header.s=google header.b=c9L85yhO;
+ spf=pass (google.com: domain of contact@restarone.com designates 209.85.220.73 as permitted sender) smtp.mailfrom=contact@restarone.com
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=google.com; s=20230601; t=1694612860; x=1695217660; dara=google.com;
+ h=to:from:subject:date:message-id:sender:reply-to:mime-version:from
+ :to:cc:subject:date:message-id:reply-to;
+ bh=jQjL48TRbWIpmFbKg7lGniGzhaf+TVo9+lJ67nhrZk4=;
+ b=4cb2kpAGWYCCzwsVOEmFpeC5eH2DOe6TeebiP7ALlgSRToIQf9jZB4/9Z5TbLBn/Bz
+ /GLRwjF5RTuz9T1FKVNMokMUThUuHfQkAcyG+tkUBbqSqBDsl9rriAJJ7OzZaV1yFsH4
+ p3yHakQ/oombYRGf9iVxrMrVpVPT27Ty4uE+CYjMCHIjg8l36iAHKGErJhVHpeVvDycn
+ RIOpaSeuDgaqWJ6cZRW5TnAuGpZf7xcgSFvJE7NU6StVTgIRaQ3h4RI0HmGwUuT6eHe/
+ Gxvzh4Zyvr4jS8j0q/IaX65Mzs9y3ZAilTlcTjZhiw9ewnnlslprSXxRtAAShiXqN3DW
+ tKVQ==
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=restarone.com; s=google; t=1694612860; x=1695217660; dara=google.com;
+ h=to:from:subject:date:message-id:sender:reply-to:mime-version:from
+ :to:cc:subject:date:message-id:reply-to;
+ bh=jQjL48TRbWIpmFbKg7lGniGzhaf+TVo9+lJ67nhrZk4=;
+ b=c9L85yhO9+lWc5YL4toKAMjgB6zObypswuclLnH0ZOl1IuODTHVuDwgZY9xlzOT4w3
+ CvGGRjWe9Idks6oXDkSExHoXAA9qKrSAd8f6RW5rmeNDlTiHYMVaSNtEc1iTyKaHuA5l
+ xO4zy5OusYCEl5q5LSyWTN1I+tJJWINKVMhds=
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=1e100.net; s=20230601; t=1694612860; x=1695217660;
+ h=to:from:subject:date:message-id:sender:reply-to:mime-version
+ :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;
+ bh=jQjL48TRbWIpmFbKg7lGniGzhaf+TVo9+lJ67nhrZk4=;
+ b=Sb+r+Abl1na8CpV0Ixdrmk7Bk/KUOT4arNsHMNG3GFKW+qMd0inEztuxkYVppq0GFq
+ i+KzwQ0HlpCWA83Thu8SLIigPPl1VsAI+nkNbX4yuG5las+/4JtlwIaDYRpIG4h+x1t+
+ WGfcmE7QcbbHg5y803tuIqp1xgpnSZQ9JCOZECiJdHyiKhRrY3Uxyg9dotCk4xgFVv8h
+ YCA18S4qy/JsVHp3BWVqch8h6PHyhMojKCdMUzyxcChG2BnGrGcVabetzHGiqvUyERRx
+ vSq5KSF/c/D9KrWod/1Xs4pv7pYjQDE+ZU+a1gdZtmWZYUzDoJjWKqilbbaTZtMCEUqr
+ z84A==
+X-Gm-Message-State: AOJu0YwNhqeENoTe+Fj9uDXO0JKv1g2PUZphLGjx3aOEW0t/yK1FSXCf
+ qJLe+otnSEuXxViGSI2/XL416S0SX3b5lARJR2RcFyHBaqUiaHM=
+X-Google-Smtp-Source: AGHT+IEWeye6hY2V3qBxbAZLOMwHDvUCYFicSIxgxL92HWng5zyOUUxp9Ub9/xvyrUBr2ZwBi67P8XTuiQVHmUP3Y20U
+MIME-Version: 1.0
+X-Received: by 2002:a05:6214:5002:b0:64f:946a:e2a6 with SMTP id
+ jo2-20020a056214500200b0064f946ae2a6mr3252403qvb.50.1694612859853; Wed, 13
+ Sep 2023 06:47:39 -0700 (PDT)
+Reply-To: contact@restarone.com
+Sender: Google Calendar
+Message-ID:
+Date: Wed, 13 Sep 2023 13:47:39 +0000
+Subject: Invitation: test meeting @ Wed Sep 13, 2023 12:30pm - 1:30pm (EDT) (restarone@restarone.solutions)
+From: contact@restarone.com
+To: restarone@restarone.solutions
+Content-Type: multipart/mixed; boundary="0000000000008b4dbe06053dcde8"
+
+--0000000000008b4dbe06053dcde8
+Content-Type: multipart/alternative; boundary="0000000000008b4dbd06053dcde6"
+
+--0000000000008b4dbd06053dcde6
+Content-Type: text/plain; charset="UTF-8"; format=flowed; delsp=yes
+Content-Transfer-Encoding: base64
+
+dGVzdCBtZWV0aW5nDQpXZWRuZXNkYXkgU2VwIDEzLCAyMDIzIOKLhSAxMjozMHBtIOKAkyAxOjMw
+cG0NCkVhc3Rlcm4gVGltZSAtIFRvcm9udG8NCg0KSm9pbiB3aXRoIEdvb2dsZSBNZWV0DQpodHRw
+czovL21lZXQuZ29vZ2xlLmNvbS9pb24tcmNkYy15cnE/aHM9MjI0DQoNCg0KCQ0KSm9pbiBieSBw
+aG9uZQ0KKENBKSArMSAyODktMzQ4LTc3NzENClBJTjogNDIwMTQ0NjA3DQoNCk1vcmUgcGhvbmUg
+bnVtYmVycw0KaHR0cHM6Ly90ZWwubWVldC9pb24tcmNkYy15cnE/cGluPTYxMjYxMjUyODcyMDUm
+aHM9MA0KDQoNCk9yZ2FuaXplcg0KY29udGFjdEByZXN0YXJvbmUuY29tDQpjb250YWN0QHJlc3Rh
+cm9uZS5jb20NCg0KUmVwbHkgZm9yIHNoYXNoaWtlamF5YXR1bmdlQGdtYWlsLmNvbSBhbmQgdmll
+dyBtb3JlIGRldGFpbHMgIA0KaHR0cHM6Ly9jYWxlbmRhci5nb29nbGUuY29tL2NhbGVuZGFyL2V2
+ZW50P2FjdGlvbj1WSUVXJmVpZD1OM056WVRadE0yWXlOSEpqWjJoMWJUVTVabVppZGpkeGFEUWdj
+MmhoYzJocGEyVnFZWGxoZEhWdVoyVkFiUSZ0b2s9TWpFalkyOXVkR0ZqZEVCeVpYTjBZWEp2Ym1V
+dVkyOXRaVEEwT1RKa09UQTFaR1UyTlRCbE9XSXpNR1ppTW1Vd01qVmpOV05rTmpVeE1tUTNPV1Zo
+WkEmY3R6PUFtZXJpY2ElMkZUb3JvbnRvJmhsPWVuJmVzPTENCllvdXIgYXR0ZW5kYW5jZSBpcyBv
+cHRpb25hbC4NCg0Kfn4vL35+DQpJbnZpdGF0aW9uIGZyb20gR29vZ2xlIENhbGVuZGFyOiBodHRw
+czovL2NhbGVuZGFyLmdvb2dsZS5jb20vY2FsZW5kYXIvDQoNCllvdSBhcmUgcmVjZWl2aW5nIHRo
+aXMgZW1haWwgYmVjYXVzZSB5b3UgYXJlIGFuIGF0dGVuZGVlIG9uIHRoZSBldmVudC4gVG8gIA0K
+c3RvcCByZWNlaXZpbmcgZnV0dXJlIHVwZGF0ZXMgZm9yIHRoaXMgZXZlbnQsIGRlY2xpbmUgdGhp
+cyBldmVudC4NCg0KRm9yd2FyZGluZyB0aGlzIGludml0YXRpb24gY291bGQgYWxsb3cgYW55IHJl
+Y2lwaWVudCB0byBzZW5kIGEgcmVzcG9uc2UgdG8gIA0KdGhlIG9yZ2FuaXplciwgYmUgYWRkZWQg
+dG8gdGhlIGd1ZXN0IGxpc3QsIGludml0ZSBvdGhlcnMgcmVnYXJkbGVzcyBvZiAgDQp0aGVpciBv
+d24gaW52aXRhdGlvbiBzdGF0dXMsIG9yIG1vZGlmeSB5b3VyIFJTVlAuDQoNCkxlYXJuIG1vcmUg
+aHR0cHM6Ly9zdXBwb3J0Lmdvb2dsZS5jb20vY2FsZW5kYXIvYW5zd2VyLzM3MTM1I2ZvcndhcmRp
+bmcNCg==
+--0000000000008b4dbd06053dcde6
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+
+
+
+
+
+
+
+
+
+
+
+ =20
+
+ =20
+
+ =20
+
+ =20
+
+
+
+
+
+
+
+
+ test meeting
Join with Google =
+Meet =E2=80=93 You have been invited by contact@restarone.com to attend an =
+event named test meeting on Wednesday Sep 13, 2023 =E2=8B=85 12:30pm =E2=80=
+=93 1:30pm (Eastern Time - Toronto).
Forwardi=
+ng this invitation could allow any recipient to send a response to the orga=
+nizer, be added to the guest list, invite others regardless of their own in=
+vitation status, or modify your RSVP. L=
+earn more
=
+
+--0000000000008b4dbd06053dcde6
+Content-Type: text/calendar; charset="UTF-8"; method=REQUEST
+Content-Transfer-Encoding: 7bit
+
+BEGIN:VCALENDAR
+PRODID:-//Google Inc//Google Calendar 70.9054//EN
+VERSION:2.0
+CALSCALE:GREGORIAN
+METHOD:REQUEST
+BEGIN:VTIMEZONE
+TZID:America/Toronto
+X-LIC-LOCATION:America/Toronto
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+TZNAME:EDT
+DTSTART:19700308T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+TZNAME:EST
+DTSTART:19701101T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTART;TZID=America/Toronto:20230913T123000
+DTEND;TZID=America/Toronto:20230913T133000
+DTSTAMP:20230913T134739Z
+ORGANIZER;CN=contact@restarone.com:mailto:contact@restarone.com
+UID:7ssa6m3f24rcghum59ffbv7qh4@google.com
+ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=
+ TRUE;CN=restarone@restarone.solutions;X-NUM-GUESTS=0:mailto:restarone
+ @gmail.com
+X-GOOGLE-CONFERENCE:https://meet.google.com/ion-rcdc-yrq
+X-MICROSOFT-CDO-OWNERAPPTID:556337145
+CREATED:20230913T134737Z
+DESCRIPTION:-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~
+ :~:~:~:~:~:~:~:~::~:~::-\nJoin with Google Meet: https://meet.google.com/io
+ n-rcdc-yrq\nOr dial: (CA) +1 289-348-7771 PIN: 420144607#\nMore phone numbe
+ rs: https://tel.meet/ion-rcdc-yrq?pin=6126125287205&hs=7\n\nLearn more abou
+ t Meet at: https://support.google.com/a/users/answer/9282720\n\nPlease do n
+ ot edit this section.\n-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:
+ ~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-
+LAST-MODIFIED:20230913T134737Z
+LOCATION:
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:test meeting
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+
+--0000000000008b4dbd06053dcde6--
+--0000000000008b4dbe06053dcde8
+Content-Type: application/ics; name="invite.ics"
+Content-Disposition: attachment; filename="invite.ics"
+Content-Transfer-Encoding: base64
+
+QkVHSU46VkNBTEVOREFSDQpQUk9ESUQ6LS8vR29vZ2xlIEluYy8vR29vZ2xlIENhbGVuZGFyIDcw
+LjkwNTQvL0VODQpWRVJTSU9OOjIuMA0KQ0FMU0NBTEU6R1JFR09SSUFODQpNRVRIT0Q6UkVRVUVT
+VA0KQkVHSU46VlRJTUVaT05FDQpUWklEOkFtZXJpY2EvVG9yb250bw0KWC1MSUMtTE9DQVRJT046
+QW1lcmljYS9Ub3JvbnRvDQpCRUdJTjpEQVlMSUdIVA0KVFpPRkZTRVRGUk9NOi0wNTAwDQpUWk9G
+RlNFVFRPOi0wNDAwDQpUWk5BTUU6RURUDQpEVFNUQVJUOjE5NzAwMzA4VDAyMDAwMA0KUlJVTEU6
+RlJFUT1ZRUFSTFk7QllNT05USD0zO0JZREFZPTJTVQ0KRU5EOkRBWUxJR0hUDQpCRUdJTjpTVEFO
+REFSRA0KVFpPRkZTRVRGUk9NOi0wNDAwDQpUWk9GRlNFVFRPOi0wNTAwDQpUWk5BTUU6RVNUDQpE
+VFNUQVJUOjE5NzAxMTAxVDAyMDAwMA0KUlJVTEU6RlJFUT1ZRUFSTFk7QllNT05USD0xMTtCWURB
+WT0xU1UNCkVORDpTVEFOREFSRA0KRU5EOlZUSU1FWk9ORQ0KQkVHSU46VkVWRU5UDQpEVFNUQVJU
+O1RaSUQ9QW1lcmljYS9Ub3JvbnRvOjIwMjMwOTEzVDEyMzAwMA0KRFRFTkQ7VFpJRD1BbWVyaWNh
+L1Rvcm9udG86MjAyMzA5MTNUMTMzMDAwDQpEVFNUQU1QOjIwMjMwOTEzVDEzNDczOVoNCk9SR0FO
+SVpFUjtDTj1jb250YWN0QHJlc3Rhcm9uZS5jb206bWFpbHRvOmNvbnRhY3RAcmVzdGFyb25lLmNv
+bQ0KVUlEOjdzc2E2bTNmMjRyY2dodW01OWZmYnY3cWg0QGdvb2dsZS5jb20NCkFUVEVOREVFO0NV
+VFlQRT1JTkRJVklEVUFMO1JPTEU9UkVRLVBBUlRJQ0lQQU5UO1BBUlRTVEFUPU5FRURTLUFDVElP
+TjtSU1ZQPQ0KIFRSVUU7Q049c2hhc2hpa2VqYXlhdHVuZ2VAZ21haWwuY29tO1gtTlVNLUdVRVNU
+Uz0wOm1haWx0bzpzaGFzaGlrZWpheWF0dW5nZQ0KIEBnbWFpbC5jb20NClgtR09PR0xFLUNPTkZF
+UkVOQ0U6aHR0cHM6Ly9tZWV0Lmdvb2dsZS5jb20vaW9uLXJjZGMteXJxDQpYLU1JQ1JPU09GVC1D
+RE8tT1dORVJBUFBUSUQ6NTU2MzM3MTQ1DQpDUkVBVEVEOjIwMjMwOTEzVDEzNDczN1oNCkRFU0NS
+SVBUSU9OOi06On46fjo6fjp+On46fjp+On46fjp+On46fjp+On46fjp+On46fjp+On46fjp+On46
+fjp+On46fjp+On46fg0KIDp+On46fjp+On46fjp+On46On46fjo6LVxuSm9pbiB3aXRoIEdvb2ds
+ZSBNZWV0OiBodHRwczovL21lZXQuZ29vZ2xlLmNvbS9pbw0KIG4tcmNkYy15cnFcbk9yIGRpYWw6
+IChDQSkgKzEgMjg5LTM0OC03NzcxIFBJTjogNDIwMTQ0NjA3I1xuTW9yZSBwaG9uZSBudW1iZQ0K
+IHJzOiBodHRwczovL3RlbC5tZWV0L2lvbi1yY2RjLXlycT9waW49NjEyNjEyNTI4NzIwNSZocz03
+XG5cbkxlYXJuIG1vcmUgYWJvdQ0KIHQgTWVldCBhdDogaHR0cHM6Ly9zdXBwb3J0Lmdvb2dsZS5j
+b20vYS91c2Vycy9hbnN3ZXIvOTI4MjcyMFxuXG5QbGVhc2UgZG8gbg0KIG90IGVkaXQgdGhpcyBz
+ZWN0aW9uLlxuLTo6fjp+Ojp+On46fjp+On46fjp+On46fjp+On46fjp+On46fjp+On46fjp+On46
+fjp+Og0KIH46fjp+On46fjp+On46fjp+On46fjp+On46fjo6fjp+OjotDQpMQVNULU1PRElGSUVE
+OjIwMjMwOTEzVDEzNDczN1oNCkxPQ0FUSU9OOg0KU0VRVUVOQ0U6MA0KU1RBVFVTOkNPTkZJUk1F
+RA0KU1VNTUFSWTp0ZXN0IG1lZXRpbmcNClRSQU5TUDpPUEFRVUUNCkVORDpWRVZFTlQNCkVORDpW
+Q0FMRU5EQVINCg==
+--0000000000008b4dbe06053dcde8--
diff --git a/test/fixtures/meetings.yml b/test/fixtures/meetings.yml
new file mode 100755
index 000000000..89bf7d773
--- /dev/null
+++ b/test/fixtures/meetings.yml
@@ -0,0 +1,23 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+ start_time: 2023-09-13 16:06:00
+ end_time: 2023-09-13 16:06:00
+ participant_emails: []
+ description: MyText
+ timezone: MyString
+ location: MyString
+ status: CONFIRMED
+ external_meeting_id: MyString
+
+two:
+ name: MyString
+ start_time: 2023-09-13 16:06:00
+ end_time: 2023-09-13 16:06:00
+ participant_emails: []
+ description: MyText
+ timezone: MyString
+ location: MyString
+ status: CONFIRMED
+ external_meeting_id: MyString2
diff --git a/test/mailboxes/e_mailbox_test.rb b/test/mailboxes/e_mailbox_test.rb
index b0047ea8b..a47a67964 100755
--- a/test/mailboxes/e_mailbox_test.rb
+++ b/test/mailboxes/e_mailbox_test.rb
@@ -378,4 +378,15 @@ class EMailboxTest < ActionMailbox::TestCase
test "new message in thread sets thread unread: true" do
# todo test https://github.com/restarone/violet_rails/blob/57739a34ea8927ba222a42d372908a82e35de8cf/app/mailboxes/e_mailbox.rb
end
+
+ test "when sent with calendar invite" do
+ Apartment::Tenant.switch @restarone_subdomain do
+ assert_difference "Message.all.reload.size", +1 do
+ assert_difference "Meeting.all.reload.size", +1 do
+ email = create_inbound_email_from_fixture('email_with_calendar_invite.eml')
+ email.tap(&:route)
+ end
+ end
+ end
+ end
end