Hiermit ist es auch mein erster Blogeintrag ueber meinen Zivildienst, da ich nun auf jedenfall den ersten Teil des Projectes fuer beendet erklaere. Vielleicht tauchen noch Fehler auf, doch werden diese hoffentlich weitaus einfach zu verstehen sein als der Ursprung dieses Problems.
Das Problem
Meine Zivildienstagentur laeuft eine Oracle(nicht von Oracle gehosted, das wir auch noch ein Spass) Apex instanz. Ueber die wird die gesammte Firma gemanaged, von anmeldungen von Privatpersonen, Planungen von Grosveranstalltungen, bis hin zum tracken ob die eigenen Autos noch vigneten haben. Aus irgendeinem Grund den wir uns nicht erklaeren koenne beginnen die App nun langsam abzuschmieren. Das Problem mit welchem ich mich hier allerdings im speciellen beschaeftigt hatte war
-
Die Emails wurden seit langem immer in den Spamordner gesendet oder von den Mail providern vollkommen abgelehnt
-
Dann weiter wurden sie gar nicht mehr versendet
Da niemand einen Plan hatte von der wirklichen Architecktur musste ich somit ueberhaupt herausfinden, was wie gehen kann, warum es jetzt nicht geht und wie ich es anschliessend loesen kann.
Die (vermutlich) urspruengliche Architektur
Nach langem suchen glaube ich einen Plan gehabt zu haben wie das system funktionieren sollte, doch ueber details bin ich mir unsicher.
-
Apex laeuft auf einem Server in Deutschland und man kann mit verschiedenen PL/SQL commands Mails verschicken. Aehnlich wie:
APEX_MAIL.ADD_ATTACHMENT( p_mail_id IN NUMBER, p_attachment IN BLOB, p_filename IN VARCHAR2, p_mime_type IN VARCHAR2); -
Unter den apex/apex_admin einstellungen haben wir dann unter den instanz settings die Mail settings gefunden, wo man die Credentials eingeben kann. Fuehrten uns dann irgendwie auf einen VPS anbieter in Portugal, wo unsere Emails vermutlich hingeschickt wurden. Was dort mit ihnen passieren sollte koennen wir nur annehmnen, aber auf jedenfall funktionierte es nicht mehr.
-
Von diesem Portugisischem provider, muessen sie dann irgendwie durch Microsoft an die Kunden verschickt werden, wie kann ich mir leider noch immer nicht erklaeren.
Wie leicht zu sehen, war das System sehr unuebersichtlich und Hilfe hatten wir nicht. Als wir den provider fragten wurden wir darauf verwiesen das brevo doch so ein gutes Freetier hatte und wir doch lieber diese benutzen sollten. Im nachhinein, wussten diese vermutlich schon was das Problem sein werde und wollten dies nicht loesen und wollte uns somit abwimmeln.
Fehlgeschlagener Versuch
Ich habe viel versucht, doch vermutlich die meiste Zeit verbrachte ich damit SMTP direkt in Microsoft Exchange aufzusetzen. Einigen Guides nach sollte dies nur mithilfe von APP Passwoertern funktionieren, da man somit ein Authentizierungssystem umgeht. Um allerdings App Passwoerter zu erstellen muesste man TFA aktivieren. Nach dem Graben durch drei Verschiedene Admin panele hatte ich es immer noch nicht geschafft, da jedes mal die aktivierung schief lief. Schliesslich wand ich mich an den Microsoft support.
Hierbei kommunizierte ich zuerst mit einem Briten, der am Ende mich beleidigte weil scheinbar das Sciencepool system so schlecht aufgesetzt war, das es dem typen ein Verbrechen nahe kam. Er leitete mich dann weiter zu einer anderen Frau, welche es auch nicht wirklich schaffte es anzuschalten, mir allerdings wenigsten sagen konnte warum nicht.
Im Endeffekt hatte Microsoft die funktionalitaet, welche ich von den App Passwoertern wollte sowieso eingestampft und so musste ein anderer Weg gefunden werden.
Microsoft Proxy Bridge
Anstelle von SMTP hatte Microsoft sein eigenes Protocol herausgebracht um mit ihren Exchangeservern zu kommunizieren, doch Apex unterstuezt dieses Protokol nicht und scheinen auch nicht sonderlich willig das zu aendern. So fand ich einen Proxy welcher von SMTP auf das Microsoft Protocol umlegte.
Denn https://github.com/simonrob/email-oauth2-proxy welchen ich auf dem server, welcher Oracle APEX laeuft habe ich, mit der python version 3.12 installiert, da die Standart version, die davor auf dem Server gelaufen waehr, die noetigen encryption module nicht unterstuezt.
Configuration
Die Bridge muss dann configuriert werden und unsere config sieht folgendermassen aus:
[SMTP-1587]
server_address = smtp.office365.com
server_port = 587
local_address = 127.0.0.1
server_starttls = True
local_starttls = False
default_user = ff@sciencepool.org
[ff@sciencepool.org]
local_no_auth = True
client_id = 46e89381-9d66-4392-b7fc-6fd6b9cf67b6
permission_url = https://login.microsoftonline.com/e17b3998-d951-487e-92e5-e68997e6e0e7/oauth2/v2.0/authorize
token_url = https://login.microsoftonline.com/e17b3998-d951-487e-92e5-e68997e6e0e7/oauth2/v2.0/token
oauth2_scope = https://outlook.office.com/SMTP.Send offline_access
redirect_uri = http://localhost
last_activity = 1773910982
token_salt = EE+W/+9yVBEe0A6uRtfOTQ==
token_iterations = 1200000
access_token = <token>
access_token_expiry = 1773927459
refresh_token = <token>
- [SMTP-1587] Ist der Stadart Port, mit welchem der Mailproxy interagiert und wird deswegen so belassen. Hierbei muss darauf geachtet werden das in der Oracle Apex Mail config, zu finden unter https://apexurl.org/apex/apex_admin -> Manage Instance(Top row) -> Instance Settings(Im Reiter von Manage Instance) -> Email -> SMTP Host Port = 1587.
- server_address Ist die addresse vom Exchange server von Microsoft
- server_port Ist der port des externen Mail servers
- server_starttls Da der externe verkehr verschluesselt sein muss(soweit ich weis) sollte dieser auf True gesetzt sein
- local_starttls Dieser Wert setzt wie local der HELLO Handshake sich abspielen soll. Vermutlich ist am wichtigsten, das dieses Setting equivalent ist, zu dem vom Apex server, doch wuerde ich aus einfachkeitsgruenden das Ausschalten empfehlen. Dazu wieder zu: apex_admin -> Manage Instance(Top row) -> Instance Settings(Im Reiter von Manage Instance) -> Email -> Use SSL/TLS = No
- default_user vermutlich nicht relevant, allerdings wenn die emails anonym verschicken wollen wuerde, ginge das nun doch ueber die default user address.
- local_no_auth is important to set to True, so that the emailproxy doesn’t take in any creadentails which could lead to problems
- client_id in the portal.azure.com, if you go to the user who manages the application, you have to create a new application and add this applications Application ID here. You can find them under Assignment Detail
- permission_url && token_url the uuid looking part of the current configuratino is the tenant ID also found on portal.azure.com under overview
- redirect_uri has to be set to http://localhost to make it possible to get the verification token, as the default would redirect you imidiatly making it hard to get the token from the url
Permissions
I don’t know how important any of these specific Permissions are, but I am just going to list all of the ones currently granted
- Microsoft Graph
- ExternalConnection.ReadWrite.All
- Mail.send
- SMTP.Send
- Office 365 Exchange Online
- SMTP.SendAsApp
All of them with Admin consent and execpt SMTP.Send of Type Application
Running the mailproxy
I then created a systemd entry with the ExecStart starting this command
emailproxy.py --config emailproxy.config --no-gui --external-auth
running this will prompt you to authenticate using the microsoft account who is managing the application until you get redirected to a url wich will not be found, because it starts with a http://localhost address. In the command line emailproxy will ask you for an url, just feed it the whole url and it will do it’s authentication from there.
This should now make it possible to send emails for the authenticated user, but not for arbitrary useres.
Outlook Mailserver
To allow the application from one user to send emails for any amount of mails under the domain, we will have to change the permission on the mailserver. This often takes a bit of time, so just because it doesn’t work imidiatly doesn’t mean the changes where not the correct ones.
- First you have to install powershell, which is also possible on Linux devices, just not supported for Open Suse
Install-Module -Name ExchangeOnlineManagement -Scope CurrentUserInstall the Exchange ModuleConnect-ExchangeOnlineConnect with the server, you will have to authenticate- Get your applications Object Id, under portal.azure.com under enterprise applications -> Your application -> Object ID
New-ServicePrincipal -AppId "<Application ID>" -ServiceId "<OBJECT_ID>"- Now for every email the application is supposed to send mails from, execute this command
Add-RecipientPermission -Identity "office@sciencepool.org" -Trustee <OBJECT_ID> -AccessRights SendAs
It took about an houre and then I had to manually send all mails in the mail que.
Result
Ich musste den systemd service nur einmal neustarten, wobei ich die authentizierung nur wirklich beim manuellen ausfuehren durchspielen kann, ansonsten lief es erstaunlich smooth. Wenn sich ueber die Zeit weitere Email addressen ergeben, ueber welche Emails gesendet werden sollten muss man diese natuerlich auch einzeln hinzufuegen.
Spannend wird die Geschichte allerdings wieder wenn das authentizierungstoken abgelaufen ist, weil das kann hier bei meinem Zivildienst niemand. Das bedeutet sie werden entweder jemanden finden, der mein Workaround versteht, oder zu mir kommen muessen.