21 sierpnia 2019 r. Microsoft ogłosił, że akcje w Microsoft Flow ze stosu Outlook zostaną przeniesione z używania interfejsu API REST programu Outlook v1.0 na Microsoft Graph v1.0. Oprócz tych informacji napisano również, że istniejące Outlook REST API v1.0 zostanie wycofane z użytku 1 listopada 2019 r. Po tej dacie wszystkie stare akcje w Microsoft Flow również zostaną usunięte.

Nie byłoby w tej tranzycji nic złego – jest ona motywowana ważnymi argumentami, jednak wraz z pozytywnymi aspektami ma jeden, znaczący negatywny problem: całkowity rozmiar wiadomości wysyłanej do API Microsoft Graph v1.0 i rozmiar każdego załącznika nie może przekroczyć 4 MB. Oznacza to, że dużych załączników po prostu nie można już wysyłać z Flow.

Trochę historii wokół tematu

Podczas przeglądania Internetu w poszukiwaniu jakiegokolwiek obejścia lub informacji o tym, kiedy problem zostanie rozwiązany, znalazłem te dwie informacje:

  1. Wpis na UserVoice: https://powerusers.microsoft.com/t5/Flow-Ideas/Send-Email-with-Option-File-Size-Limit/idi-p/337826 – potwierdzający, że jest to bolączka wielu użytkowników…
  2. Dyskusja na Github: https://github.com/microsoftgraph/microsoft-graph-docs/issues/4370#issuecomment-536143650

Ta na github sprawiła, że poczułem się nieco lepiej, ponieważ przeczytałem tam, że Microsoft planuje już za kilka tygodni wypuścić aktualizację w wersji beta, pozwalającą na wysyłanie wiadomości z załącznikami większymi, choć bez dokładnej informacji, jak bardzo. Ale „tygodnie” mogą oznaczać 2 lub 10. A wymóg jednego z moich klientów był bardzo jasny i pilny – musimy być w stanie wysyłać załączniki większe niż 4 MB za pomocą Flow.

Obejście aka rozwiązanie

Rozwiązaniem dla limitu 4 MB dla załączników wysyłanych z Microsoft Flow, o którym najczęściej wspominano (użytkownik Alhric Lacle udostępnił nawet kawałek kodu CSOM) było zalecenie skorzystania z interfejsu Outlook REST API v2.0, który nie zostanie wycofany (a przynajmniej w chwili pisania tego postu nie było żadnych informacji na ten temat), a który limitu nie posiada.

Pomysł na początku wydał mi się dość prosty:

  1. Stworzenie aplikacji Azure AD
  2. Nadanie jej uprawnień dla zakresów Mail.ReadWrite i Mail.Send
  3. Nadanie uprawnień administratora
  4. Użycie jednej akcji HTTP request do odpytania endpoint autoryzacyjnego w celu pobrania tokenu Bearer
  5. Użycie tokenu do poświadczenia akcji wysłania wiadomości e-mail z załącznikami korzystając z metody opisanej w dokumentacji: https://docs.microsoft.com/en-us/previous-versions/office/office-365-api/api/version-2.0/mail-rest-operations.

Podczas testu z aplikacją Postman zdałem sobie sprawę, że jest to jednak niemożliwe. Mimo, że udało mi się zdobyć Bearer token, nie mogłem odpytać endpoint w celu wysłania e-mail, ponieważ ciągle otrzymywałem odmowę dostępu.

Myślę, że powodem tego był fakt, że aplikacja została zarejestrowana w kontekście aplikacji, a nie użytkownika, a interfejs API oczekiwał kontekstu użytkownika. Ale to tylko moje przypuszczenie.

Niemniej jednak po kilkukrotnym niepowodzeniu poprosiłem na Twitterze o pomoc:

Pomoc nadeszła od Vivek Bavishi (dzięki kolego!). Zasugerował, by użyć istniejącej akcji w Microsoft Flow zwanej „Invoke an HTTP request” z grupy „HTTP with Azure AD„.

Ważne! Te akcje należą do grupy premium. Potrzebna jest licencja per flow lub per użytkownik by móc ich używać.

Postanowiłam spróbować. Największą różnicą między użyciem wbudowanych działań, a akcją „HTTP request” jest to, że w podejściu OOTB tak naprawdę nie ma potrzeby odpytywania wpierw endpoint autoryzacyjnego, w celu uzyskania Bearer token.

Ważne! Wszystkie nazwy w schemacie JSON są camelCased. Także upewnij się, że kopiujesz je 1-1 z przykładów dostępnych w dokumentacji.

Zdecydowałem się użyć endpoint nazywającego się: https://outlook.office.com/api/v2.0/users/{USER-EMAIL}/sendmail w celu wysłania wiadomości e-mail ze skrzynki współdzielonej.

Ważne! Podczas tworzenia połączenia upewnij się, że używasz poświadczeń użytkownika, który ma uprawnienia do wysyłania w imieniu innego użytkownika/ współdzielonej skrzynki pocztowej. To jest kluczowy punkt tego rozwiązania.

Chciałem też, aby moja wiadomość została wysłana do wielu odbiorców. W schemacie istnieją dwie tablice:

"ToRecipients": [   ],
"CcRecipients": [   ],

W każdej z nich należy umieścić e-mail każdego odbiorcy w osobnym bloku:

{
  "EmailAddress": {
    "Address": "SINGLE EMAIL ADDRESS"
  }
}

Tym samym nie ma możliwości wstawienia po prostu stringu z adresami e-mail, rozdzielonymi średnikiem.

Treść dla tych bloków przygotowałem w następujący sposób: najpierw podzieliłem, a następnie natychmiast połączyłem listę adresów e-mail rozdzielonych średnikami, używając poniższego wyrażenia:

split(body('mail1@test.com;mail2@test.com', ';')

W tym celu użyłem akcji nazwanej „Join”. Ciągiem użytym jako łącznik „Join with” był:

"}},{"EmailAddress": { "Address": "

I dzięki temu wynik idealnie wpasował się do wnętrza bloku:

{
  "EmailAddress": {
    "Address": "OUTCOME OF THE JOIN ACTION"
  }
}

Następnym krokiem jest dołączenie załączników. Najważniejszą rzeczą do zapamiętania jest to, że zawartość pliku musi być zakodowana w standardzie base64. Pliki są przechowywane w tablicy o nazwie „Attachments”:

"Attachments": [   ]

Każdy załącznik jest obiektem zbudowanym z poniższych atrybutów:

{
  "@odata.type": "#Microsoft.OutlookServices.FileAttachment", 
  "Name": "FILENAME", 
  "ContentBytes": "BASE64 ENCODED FILE CONTENTS"
}

Istnieją również dodatkowe opcje w schemacie, takie jak „SaveToSentItems”, jednak głównym rdzeniem akcji są adresaci, zawartość wiadomości e-mail i załączniki. Ostateczne działanie polegające na wysłaniu poczty w locie wygląda następująco:

Największy plik, który próbowałem wysłać miał 18 MB, jednak powinno być również możliwe wysyłanie plików do 50 MB.

Mam nadzieję, że ten post będzie dla Ciebie pomocny. I pozwoli Ci on zaoszczędzić dużo czasu na szukaniu sposobu na obejście nowego limitu. Mam również osobiście nadzieję, że zapisane tutaj informacje wkrótce staną się bezużyteczne z powodu wzrostu limitu obecnego w Graph API v1.0 😉

Zostań w kontakcie!