Zum Inhalt

Interacting with EWS

The following two projects have been tested are known to work well with the Kopano Cloud EWS implementation.

Note

A lot of calls require E4A_ENABLE_EWS_EXPERIMENTAL_OPERATIONS=true to be set as an environment in the container.

Examples

With the following example script the out of office settings of a user can be retrieved:

#!/usr/bin/env python

import argparse
import exchangelib
import logging
import os
import pprint


def get_user_oof_settings(autodiscover, url, username, password, smtp_address):
    creds = exchangelib.Credentials(username, password)

    if False:
        # Set version client side, as the automatic version discovery is an extra
        # request which we do not support.
        version = exchangelib.Version(build=exchangelib.version.EXCHANGE_2007_SP1)
    else:
        version = None

    if autodiscover:
        account = exchangelib.Account(
            primary_smtp_address=smtp_address, credentials=creds, autodiscover=True, access_type=exchangelib.DELEGATE
        )
    else:
        config = exchangelib.Configuration(service_endpoint=url, credentials=creds, version=version)
        account = exchangelib.Account(
            primary_smtp_address=smtp_address, config=config, autodiscover=False, access_type=exchangelib.DELEGATE
        )

    # Fetch OOF settings.
    oof_settings = account.oof_settings

    return oof_settings


def main():
    parser = argparse.ArgumentParser(description="Retrieve OOF settings using Exchange Web Services.")

    parser.add_argument("--autodiscover", action="store_true", help="Enable autodiscovery (default: False)")
    parser.add_argument(
        "--url",
        type=str,
        default="https://exchange4all.local/EWS/Exchange.asmx",
        help="The URL to Exchange.asmx if autodiscover is not used",
    )
    parser.add_argument("--username", type=str, required=True, help="The username for authentication")
    parser.add_argument("--password", type=str, required=True, help="The password for Basic authentication")
    parser.add_argument("--smtp-address", type=str, required=True, help="The SMTP address of the mailbox")

    args = parser.parse_args()

    # Make requests use the system certificates (Linux only).
    os.environ["REQUESTS_CA_BUNDLE"] = "/etc/ssl/certs/ca-certificates.crt"

    if True:
        from exchangelib.util import PrettyXmlHandler

        logging.basicConfig(level=logging.DEBUG, handlers=[PrettyXmlHandler()])

    try:
        oof_settings = get_user_oof_settings(
            autodiscover=args.autodiscover,
            url=args.url,
            username=args.username,
            password=args.password,
            smtp_address=args.smtp_address,
        )
    except Exception as e:
        print(f"Error: {e}")
        exit(1)
    finally:
        exchangelib.close_connections()

    print("Success!\n")
    pprint.pp(oof_settings, indent=4)


if __name__ == "__main__":
    main()

Example for user .NET:

using System;
using System.CommandLine;

using Microsoft.Exchange.WebServices.Data;

namespace GetUserOofSettings;

class Program
{
    static async Task<int> Main(string[] args)
    {
        var rootCommand = new RootCommand("Simple EWS example to retriefe OOF settings");

        var autoDiscoverOption = new Option<bool>(
            "--autodiscover",
            description: "Enable autodiscovery (default: false) (if set, the --url flag is ignored) (works on Windows only!)"
        );
        rootCommand.AddGlobalOption(autoDiscoverOption);

        var urlOption = new Option<string>(
            "--url",
            description: "The URL to Exchange.asmx (required if autodiscover is not used)", getDefaultValue: () => "https://exchange4all.local/EWS/Exchange.asmx");
        rootCommand.AddGlobalOption(urlOption);

        var usernameOption = new Option<string>(
            "--username",
            description: "The username (for autodiscovery and/or Basic authentication)")
        {
            IsRequired = true,
        };
        rootCommand.AddGlobalOption(usernameOption);

        var passwordOption = new Option<string>(
            "--password",
            description: "The password for Basic authentication");
        rootCommand.AddGlobalOption(passwordOption);

        var accessTokenOption = new Option<string>(
            "--access-token",
            description: "The acesss token (if set, use Bearer authentication)");
        rootCommand.AddGlobalOption(accessTokenOption);

        var smtpAddressOption = new Option<string>(
            "--smtp-address",
            description: "The SMTP address of the mailbox")
        {
            IsRequired = true
        };
        rootCommand.AddOption(smtpAddressOption);

        int returnCode = 0;
        rootCommand.SetHandler(async (bool autodiscover, string url, string username, string password, string accessToken, string smtpAddress) =>
        {
            returnCode = await DoGetUserOofSettings(autodiscover, url, username, password, accessToken, smtpAddress);
        }, autoDiscoverOption, urlOption, usernameOption, passwordOption, accessTokenOption, smtpAddressOption);
        await rootCommand.InvokeAsync(args);
        return returnCode;
    }


    public static async Task<int> DoGetUserOofSettings(bool autodiscover, string url, string username, string password, string acessToken, string smtpAddress)
    {
        ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
        service.Credentials = new WebCredentials(username, password);
        service.TraceEnabled = true;
        service.TraceFlags = TraceFlags.All;
        service.UseDefaultCredentials = false;
        service.EnableScpLookup = false;

        if (autodiscover)
        {
            // Autodiscovery does not work very good on Linux as the hack in
            // https://github.com/sherlock1982/ews-managed-api/blob/a5c23339b30a773dac5b3c740d3df6a1a4c7ac76/Autodiscover/AutodiscoverService.cs#L1547 is not working and fails
            // with exception as it lacks a check for url != null. Also for
            // any requested server version > Exchange2007_SP1 this also fails
            // on linux since the Legacy service is nver tried as the exception
            // for DNS srv will be reached first (since we don't support the
            // SOAP based autodiscovery)
            // See tests/dotnet-example/GetUserOofSettings/GetUserOofSettings.csproj
            // how to install a partly fixed version.
            await service.AutodiscoverUrl(username, RedirectionUrlValidationCallback);
        }
        else
        {
            service.Url = new Uri(url);
        }

        OofSettings oofsettings = await service.GetUserOofSettings(smtpAddress);
        Console.WriteLine(ObjectDumper.Dump(oofsettings, DumpStyle.CSharp));


        return 0;
    }

    private static bool RedirectionUrlValidationCallback(string redirectionUrl)
    {
        // The default for the validation callback is to reject the URL.
        bool result = false;
        Uri redirectionUri = new Uri(redirectionUrl);
        // Validate the contents of the redirection URL. In this simple validation
        // callback, the redirection URL is considered valid if it is using HTTPS
        // to encrypt the authentication credentials.
        if (redirectionUri.Scheme == "https")
        {
            result = true;
        }
        return result;
    }

}