반응형

Previous Post

2024.09.16 - [Microsoft 365/Graph & IIS] - Microsoft Graph & IIS. (5) Sending emails using the Mail.send permission

 

 

https://youtu.be/YeCf5GNVzf0

 

 

This time, let's add an Email tab to display the contents of Mailfolders.

Currently, the design looks like this. We will add the Email tab between Home and Privacy.

 

_layout.cshtml

 

Add the following content as shown below.

<li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Mailfolders">Email</a>
</li>

 

Confirm that the addition has been successfully made.

 

 

When clicked, it will be displayed as shown below.

 

반응형
반응형

Previous post

2024.09.16 - [Microsoft 365/Graph & IIS] - Microsoft Graph & IIS. (4) Display Mailbox using the Mail.read permission

 

Continuing from the previous post, this time we will implement the functionality to compose and send emails using the Mail.Send permission of the Graph API.

We'll continue using the project created in the previous post.

 

https://youtu.be/KReqV8EPVh0

 

The process pattern is somewhat established at this point:

Step 1: Add Mail.Send permission

Step 2: Create a ViewModel for sending emails

Step 3: Create a View for composing and sending emails

Step 4: Add the Action Method for sending emails

 

Step 1. Add Mail.Send permission

Appsettings.json

 

Add Mail.Send permission.

 

 

Step 2. Create a View Model for Sending Emails

Create the EmailSendViewModel to hold the data needed for sending emails. This model will include fields like recipient address, email subject, and email body.

 

Create the EmailSendViewModel class

public class EmailSendViewModel
{
        public string To { get; set; } = string.Empty;
        public string Subject { get; set; } = string.Empty;
        public string Body { get; set; } = string.Empty;
}

 

Step 3. Create a View for Sending Emails

Create a view (SendEmail.cshtml) in the Views/Home directory, where users can compose and send emails. This view will use the EmailSendViewModel as its model.

 

Create SendEmail.cshtml

 

Modify the content as shown below.

@model Identity.Models.EmailSendViewModel

<h2>Send Email</h2>

<form asp-action="SendEmail">
    <div class="form-group">
        <label>To</label>
        <input asp-for="To" class="form-control" />
    </div>
    <div class="form-group">
        <label>Subject</label>
        <input asp-for="Subject" class="form-control" />
    </div>
    <div class="form-group">
        <label>Body</label>
        <textarea asp-for="Body" class="form-control"></textarea>
    </div>
    <button type="submit" class="btn btn-primary">Send</button>
</form>

 

Step 4. Add Action Method for Sending Emails

Add the SendEmail action method to the HomeController. This method accepts EmailSendViewModel as a parameter and sends an email using the Microsoft Graph API.

 

Modify HomeController.cs.

 

Add the following content.

// GET action method to display the email sending form
[HttpGet]
public IActionResult SendEmail()
{
    return View(new EmailSendViewModel()); // Pass an empty model to the view
}

// Sendemail
[HttpPost]
[AuthorizeForScopes(ScopeKeySection = "MicrosoftGraph:Scopes")]
public async Task<IActionResult> SendEmail(EmailSendViewModel model)
{
    var message = new Message
    {
        Subject = model.Subject,
        Body = new ItemBody
        {
            ContentType = BodyType.Text,
            Content = model.Body
        },
        ToRecipients = new List<Recipient>()
        {
            new Recipient
            {
                EmailAddress = new EmailAddress
                {
                    Address = model.To
                }
            }
        }
    };

    await _graphServiceClient.Me.SendMail(message, null).Request().PostAsync();

    return RedirectToAction("Index");
}

 

Navigate to the Home/sendemail URL.

 

 

Send a test email

 

The test email has been received.

반응형
반응형

Previous Post:

2024.09.16 - [Microsoft 365/Graph & IIS] - Microsoft Graph & IIS. (3) Creating a sample login page using the Microsoft Identity Platform

 

Continuing from the previous post, this time we will use the Mail.Read permission in the Graph API to retrieve mail folders, subject lines, and content, and publish them on IIS.

We will continue using the project created in the previous post.

 

https://youtu.be/tOCCgRloYOo

 

Step 1. Testing Mail.Read Permission

We will test the Mail.Read permission by retrieving only the subject lines of the user's emails on a specific page.

Add the Mail.Read permission to the existing Appsettings.json -> Save the file.

 

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "M365x31504705.onmicrosoft.com",
    "TenantId": "a0c898ca-2445-4e74-ab4b-afd7916549a6",
    "ClientId": "726cf3c0-8faa-4b91-a3dc-4ec4723a411b",
    "CallbackPath": "/signin-oidc"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "MicrosoftGraph": {
    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "user.read mail.read" //Add Mail.read
  }
}

 

 

Modify the HomeController.cs file

 

Add the //Email Titles section to the existing code as shown below.

 

using Identity.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using Microsoft.Graph;
using Microsoft.Identity.Web;

namespace Identity.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        private readonly GraphServiceClient _graphServiceClient;
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger, GraphServiceClient graphServiceClient)
        {
            _logger = logger;
            _graphServiceClient = graphServiceClient;
        }

        [AuthorizeForScopes(ScopeKeySection = "MicrosoftGraph:Scopes")]
        public async Task<IActionResult> Index()
        {
            var user = await _graphServiceClient.Me.Request().GetAsync();
            ViewData["GraphApiResult"] = user.DisplayName;
            return View();
        }

        // Email Titles
        [AuthorizeForScopes(ScopeKeySection = "MicrosoftGraph:Scopes")]
        public async Task<IActionResult> EmailTitles()
        {
            var messages = await _graphServiceClient.Me.Messages
                .Request()
                .Select(m => new { m.Subject })
                .GetAsync();

            var titles = messages.Select(m => m.Subject).ToList();
            return View(titles);
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [AllowAnonymous]
        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

 

Create the View.

Views -> Home -> Add -> View

 

Razor View -> Empty -> Add

 

EmailTitles.cshtml -> Add

 

It will be generated as shown below.

 

Modify the content as follows.

@model List<string>

<h2>Email Titles</h2>
<ul>
@foreach (var title in Model)
{
    <li>@title</li>
}
</ul>

 

Start Debuging -> Log in -> Verify permissions and click Accept.

 

When you navigate to the Home/emailtitles URL, it will be displayed as shown below.

 

When compared with OWA (Outlook Web App), you can see that only the email subjects have been retrieved.

This time, let's create a page that retrieves and displays emails in the following structure: Folder -> Subject -> Body.

 

Step2. Action Method

Action Methods in the controller handle HTTP requests and retrieve data by calling the Microsoft Graph API. We will implement Action Methods such as MailFolders, EmailTitles, and EmailDetails to fetch the list of mail folders, the list of emails in a specific folder, and the detailed content of an email, respectively.

 

Modify the HomeController.cs file

 

Remove the existing Email Titles code.

 

Insert the code for Mail Folders, Titles, and Details respectively.

//MailFolders
public async Task<IActionResult> MailFolders()
{
    var mailFolders = await _graphServiceClient.Me.MailFolders
        .Request()
        .GetAsync();

    return View(mailFolders.CurrentPage.Select(f => new MailFolderViewModel { Id = f.Id, DisplayName = f.DisplayName }).ToList());
}

//EmailTitles
public async Task<IActionResult> EmailTitles(string folderId)
{
    var messages = await _graphServiceClient.Me.MailFolders[folderId].Messages
        .Request()
        .Select(m => new { m.Subject, m.Id })
        .GetAsync();

    var titles = messages.CurrentPage.Select(m => new EmailViewModel { Id = m.Id, Subject = m.Subject }).ToList();
    return View(titles);
}

//EmailDetails
public async Task<IActionResult> EmailDetails(string messageId)
{
    var message = await _graphServiceClient.Me.Messages[messageId]
        .Request()
        .Select(m => new { m.Subject, m.Body })
        .GetAsync();

    var model = new EmailDetailsViewModel
    {
        Subject = message.Subject,
        BodyContent = message.Body.Content
    };

    return View(model);
}

 

Step3. View model

A View Model is a model used to pass data to the View and is used to define the data retrieved from the Action Method. For example, the EmailViewModel includes the email's ID and subject. This allows the data needed in the view to be structured and managed efficiently.

 

Right-Click on the Models folder -> Add -> Class

 

MailFolderViewModel.cs -> Add

 

It will be generated as shown below.

 

Modify it as shown below.

 

namespace Identity.Models
{
    public class MailFolderViewModel
    {
        public string Id { get; set; }
        public string DisplayName { get; set; }
    }
}

 

Similarly, go to Models -> Add -> Class.

 

EmailViewModel.cs -> Next

 

Modify it as shown below -> Save.

namespace Identity.Models
{
    public class EmailViewModel
    {
        public string Id { get; set; }
        public string Subject { get; set; }
    }
}

 

Add EmailDetailsViewModel.cs in the same way.

 

Modify it as shown below -> Save.

public class EmailDetailsViewModel
{
    public string Subject { get; set; }
    public string BodyContent { get; set; }
}

 

Step 4. View

Finally, the View constructs the user interface and displays the data received from the View Model. Create corresponding view files for each action in the Views/Home directory.

 

Views/Home Folder -> Add -> New Item

 

MailFolders.cshtml -> Add

 

Modify as shown below and save.

@model IEnumerable<Identity.Models.MailFolderViewModel>

<h2>Mail Folders</h2>
<ul>
    @foreach (var folder in Model)
    {
        <li><a href="@Url.Action("EmailTitles", "Home", new { folderId = folder.Id })">@folder.DisplayName</a></li>
    }
</ul>

 

Modify the previously created Emailtitles.cshtml file.

@model IEnumerable<Identity.Models.MailFolderViewModel>

<h2>Mail Folders</h2>
<ul>
    @foreach (var folder in Model)
    {
        <li><a href="@Url.Action("EmailTitles", "Home", new { folderId = folder.Id })">@folder.DisplayName</a></li>
    }
</ul>

 

Modify the previously created Emailtitles.cshtml file.

 

Modify it as shown below and save.

@model IEnumerable<Identity.Models.EmailViewModel>

<h2>Emails</h2>
<ul>
    @foreach (var email in Model)
    {
        <li><a href="@Url.Action("EmailDetails", "Home", new { messageId = email.Id })">@email.Subject</a></li>
    }
</ul>

 

Create EmailDetails.cshtml in the same manner as the previously created files.

EmailDetails.cshtml -> Add

@model Identity.Models.EmailDetailsViewModel

<h2>@Model.Subject</h2>
<div>
    @Html.Raw(Model.BodyContent)
</div>

 

Start Debugging

 

Access the path /home/mailfolders.

 

The list of folders is displayed. Click on Inbox.

 

You can now see the list of emails in the Inbox. Click on the email subject to view more details.

 

The email body is displayed.

 

Proceed with the Publish and IIS deployment process as in the previous post. Verify the functionality as shown below.

 

반응형
반응형

Last Post

2024.09.16 - [Microsoft 365/Graph & IIS] - Microsoft Graph & IIS. (2) Publishing an ASP.NET Sample Page to IIS

 

 

In this post, we will create a login page in IIS using an M365 (Entra ID) sample login page.

https://youtu.be/hb7ZDVwJWEE

 

Launch Visual Studio -> Create a new project

 

ASP.NET Core Web App (Model-View-Controller)

 

Specify the Project name-> Next

 

Authentication type -> Microsoft identity platform -> Create

 

Next

 

Sign in -> Microsoft

 

Log in with the administrator account.

 

Create new

 

A browser window pops up. Log in with the administrator account.

 

Authentication complete.

 

Specify the Display name. -> Register

 

Confirm that the creation is successful.-> Next

 

Add Microsoft Graph permissions -> Next

 

Save the Client secret value in a notepad.-> Next

 

Finish

 

Close

 

Close

 

Service is registered, and verify that Secrets.json (Local) has been created.

 

Double-click on the Appsettings.json file.

 

The information for the created app is displayed.

 

The same information is confirmed in Entra ID.

 

Start Debugging

 

After accessing localhost, you're redirected directly to the login page -> Log in with the administrator account.

 

Upon first access, the permissions are displayed as shown below -> Click Accept. -> Accept

 

Display the logged-in account information.

 

When you sign out, the following message is displayed.

 

When you log in with a different account, it displays the information of that account.

 

Build -> Identity

 

Web Server (IIS) -> Next

 

Web Deploy Package -> Next

 

Specify the location to export the package -> Set the Site Name -> Click Finish.

 

Close

 

Publish

 

Once completed, copy the package file to the IIS Server.

 

As done in the previous post, after extracting the files, copy the essential folders and files, such as wwwroot, to the root directory as shown below.

 

Launch IIS Manager

 

Righ-Click on Sites -> Add Website

 

Specify the settings as shown below.

 

When testing on localhost, an Error 500 occurs as shown below. The cause is that the ClientSecret value is not included during publishing, which leads to this issue.

 

Open the Appsettings.json file using Notepad.

 

Add the previously saved Secret Value in the following format -> Save the file:

 

IISRESET

 

Confirm the login process.

 

Proceed with testing by accessing the published URL.

 

A Redirect URI error has occurred.

 

Entra ID Admin center -> Applications -> App registration -> Authentication -> Add the following to Redirect URIs as shown below.

 

Confirm the login process.\

반응형
반응형

Previous Post

2024.09.16 - [Microsoft 365/Graph & IIS] - Microsoft Graph & IIS. (1) Setting up the basic testing environment.

 

In this post, we will cover the process of publishing an ASP.NET Sample Page to IIS. Since most Microsoft solutions are based on ASP.NET, I thought this would be a necessary step before testing Graph.

 

https://youtu.be/6z7HdW6IoCI

 

 

Launch Visual Studio.

 

File -> New -> Project

 

ASP.NET Core Web App (Model-View-Controller) -> Next

 

Next

 

Verify that the Framework is set to .NET 8.0 -> Click "Create" (You will need to install the Runtime and SDK version 8.0 on IIS to match this setting.)

 

Solution Explorer -> Controllers -> Add -> Controller

 

MVC Controller - Empty -> Add

 

Name the controller as HelloWorldController. -> Add

 

 

Right-Click on Views -> Add -> New Folder

 

Name it HelloWorld.

 

Right-click on HelloWorld.-> Add -> New Item

 

If the following options appear, select Show All Templates.

 

Razor View - Empty -> Confirm the name as Index.cshtml. -> Add

 

Verify that it has been created under the HelloWorld folder.

 

다음과 같이 입력합니다.

ViewData["Title"] = "Index";

<h2>Index</h2>
<p>Hello from the HelloWorld view!</p>

 

Debug -> Start Debugging

 

If any messages related to SSL certificates appear, click "Yes" for all of them.

 

Yes

 

Yes

 

Yes

 

The sample page is now accessible in Edge.

 

When you access /HelloWorld, it is displayed as follows:

 

Now, let's proceed with creating the sample page as a site in IIS.

Build -> Publish [Project Name]

 

Web Server (IIS) -> Next

 

Web Deploy Package -> Next

 

Specify the location. -> Site name 지정 -> Finish

 

Click Publish.

 

It will be generated as shown below. Now, copy the files to the IIS server.

 

After copying, extract the files.

 

After extracting, move the files to a subfolder as shown below -> Copy the folder and files to the root directory (C:\Sample).

 

Copy completed.

 

Launch IIS Manager.

 

Sites -> Add Website

 

Proceed with the creation process as shown below. (For the certificate, specify the one that was previously created.)

 

Confirm that the creation is successful.

 

Application Pools -> Double-click on **Sample**.

 

.NET CLR version -> Change the setting to **No Managed Code**.

 

IISRESET

 

Access localhost to verify the setup.

 

Once DNS registration and certificate binding are completed, test the published URL.

반응형
반응형

Last post

2024.07.06 - [Microsoft 365/Entra ID] - Microsoft Entra ID. Set up tenant restrictions v2 by GPO (English)

 

Continuing from the previous post, this time we will proceed with setting tenant restrictions using GSA.

 

Youtube (English)

https://youtu.be/PIfHu4yPjN4

 

 

Step 1 is the same process as in the previous post.

The client PC has already been joined to Entra ID in advance.

 

Step 1: Configure default tenant restrictions v2

Entra Admin Center > Cross-tenant access settings > cross-tenant access settings > Default settings

 

 

Edit tenant restrictions defaults

 

 

Create Policy

 

 

The Policy ID is generated as shown below. Make sure to copy each value and keep them.

 

 

To set up a blocking policy for external accounts, configure it as shown below (default settings).

 

 

To block all external apps, configure the settings as shown below.

 

 

Step 2: Configure GSA

Click on Global Secure Access -> Activate to enable it.

 

 

Connect -> Traffic forwarding -> Activate each profile.

 

 

Proceed with assigning users and groups.

 

 

Assign to all users -> Yes

 

 

Secure -> Security profiles -> Create profile

 

 

Enter the profile name.

 

 

Link policy -> Existing policy

 

 

Link the default policy -> Proceed with the profile creation process.

 

 

Baseline profile

 

 

Change to Enabled status.

 

 

Step 3: Install GSA Client

Connect -> Client download

 

 

Download client (When deploying to actual users, Intune can be utilized.)

 

 

Proceed with the installation process of the GSA Client.

 

 

Sign in

 

 

Verify the connection status as shown below.

 

 

When logging in to a different tenant in Chrome, you can confirm that it is blocked as shown below.

 

 

The downside of the preview version is that the client has a Pause button.

 

 

Once officially released, it is expected to be built into the Windows service, similar to MDE.

 

반응형
반응형

I will discuss Tenant restriction settings.

The primary purpose of Conditional Access is to prevent company accounts from being accessed on personal devices. However, Conditional Access cannot prevent other company accounts from being accessed on company devices.

Of course, if a company device can access Naver Mail and Google Drive, it means the company is not very concerned about data leakage, and you may disregard this post.

To use M365, you need to open MS-related URLs such as office.com. Tenant Restriction is a concept used to prevent access with other company or personal accounts (such as outlook.com) during this time.

 

Youtube (English)

https://youtu.be/z-sVlZoz3y8

 

 

Technical article

Configure tenant restrictions - Microsoft Entra ID - Microsoft Entra External ID | Microsoft Learn

 

There are three main methods:

  1. GSA
  2. Company Proxy Equipment
  3. GPO

The method using GSA requires a prior understanding of GSA.

I will cover that part separately later.

In this post, I will apply tenant restrictions using the third option, GPO.

 

Step 1: Configure default tenant restrictions v2

Entra Admin Center > Cross-tenant access settings > cross-tenant access settings > Default settings

 

 

Edit tenant restrictions defaults

 

 

Create Policy

 

 

The Policy ID is generated as shown below. Make sure to copy each value and keep them.

 

 

To set up a blocking policy for external accounts, configure it as shown below (default settings).

 

 

To block all external apps, configure the settings as shown below.

 

Step 2: Enable tenant restrictions on Windows managed devices (preview)

In the technical documentation, there are guidelines as shown below.

Tenant restrictions V2 on Windows is a partial solution that protects the authentication and data planes for some scenarios. It works on managed Windows devices and does not protect .NET stack, Chrome, or Firefox. The Windows solution provides a temporary solution until general availability of Universal tenant restrictions in Microsoft Entra Global Secure Access (preview).

-> Although the content is difficult to understand, it can be interpreted as indicating that the feature will be provided in a different way in the future. Currently, it is in the preview stage.

 

Download the ADMX files for the latest Windows GPO policies.

Download Administrative Templates (.admx) for Windows 11 2023 Update (23H2) from Official Microsoft Download Center

 

Once installed, the policy files will be saved to the following location.

 

 

Depending on the method of policy deployment in AD, copy the PolicyDefinitions folder to the appropriate location with only the necessary languages. (This part of the policy is related to AD, so we will not cover it here.)

 

Run gpmc.msc on the Domain Controller (DC).

 

 

Create a policy in the Organizational Unit (OU) that you will use for testing. Right-click and select "Edit".

 

 

Computer Configuration > Administrative Templates > Windows Components > Tenant Restrictions

 

 

Configure the settings as shown below.

 

 

Attempt to log in with a personal account on Edge.

 

 

Verify that access is blocked as shown below.

 

 

You can also see that access is blocked when attempting to log in with another tenant account.

반응형
반응형

There has always been a need to synchronize address books (GAL) between companies in scenarios such as M&A, affiliated companies, or group companies, where using a single tenant is not possible. Traditionally, this was achieved by setting up servers like Microsoft Identity Manager (MIM) on an On-Premise Exchange Server, creating objects between ADs to synchronize address books. Alternatively, it could be implemented through HR integration solutions.

 

However, adopting MIM or HR integration solutions can be prohibitively expensive and requires specialized knowledge for management, making it very burdensome.

 

Recently, it has become possible to synchronize address books with Cross-tenant Synchronization. Specifically, this functionality automates the invitation of Guests.

 

https://youtu.be/-HtT_uuDul0

 

 

 

The following content was written based on the technical documentation below.

Configure cross-tenant synchronization - Microsoft Entra ID | Microsoft Learn

 

Settings are configured separately for the Source Tenant and the Target Tenant.

Step 1: Plan your provisioning deployment

First, collect the information for the Source Tenant and the Target Tenant.

Source Tenant

Domain: Contoso.kr

Tenant ID: a0c898ca-2445-4e74-ab4b-afd7916549a6

 

Target Tenant

Domain: fabrikam.kr

Tenant ID: afab079d-1f08-4de3-881e-435e497f923f

 

Step 2: Enable user synchronization in the target tenant

 

Entra Admin Center > External Identities > Organizational settings > Add organization

 

 

Enter the Source Tenant ID information. > Add

 

 

Inbound access > Inherited from default

 

 

Allow users sync into this tenant > Check

 

Step 3: Automatically redeem invitations in the target tenant

Trust settings > Automatically redeem invitations with the tenant [Tenant Name] > Check > Save

 

Step 4: Automatically redeem invitations in the source tenant

Entra Admin Center > External Identities > Cross-tenant access settings

 

 

Add organization

 

 

Enter Target Tenant ID > Add

 

 

Outbound access > Inherited from default

 

 

Trust settings > Automatically redeem invitations with the tenant Fabrikam > Check > Save

 

Step 5: Create a configuration in the source tenant

 

Cross-tenant synchronization

 

 

Configurations > New configuration

 

 

Specify the configuration name. > Create

 

Step 6: Test the connection to the target tenant

Get started

 

 

Provisioning Mode: Automatic > Admin Credentials > Tenant Id: Target Tenant ID > Test Connection > Save

 

Step 7: Define who is in scope for provisioning (Source Tenant)

Provisioning > Settings > Confirm Scope  > Sync only assinged users and groups:

This means specifying only certain users or groups to synchronize.

 

Users and groups  -> Add user/group

 

 

None Selected

 

 

Specify the target. > Select > Assign

 

Step 9: Review attribute mappings

If, for various reasons, you do not want to synchronize specific attributes, proceed as follows.

 

Provisioning > Mappings > Provision Microsoft Entra ID Users

 

 

You can remove some items except for the required fields.

 

 

Step 10: Start the provisioning job

Start provisioning

 

 

Target Tenant > Entra admin center > Users > All Users

 

 

You can verify that they are added as guests as shown below.

 

 

You can also verify this in the Exchange Admin Center as shown below.

 

 

You can also verify this in the address book as shown below.

 

 

Tenant-to-tenant synchronization settings are configured as follows: In the Source Tenant, set up the Outbound settings, and in the Target Tenant, set up the Inbound settings. This synchronization process results in Guest accounts. Since Guest accounts have Mail User attributes, they can be verified in the address book.

반응형
반응형

I am starting my blog in English for the first time.

The purpose is to make it easier to use commands or scripts provided in the videos on YouTube.

The topic for this week is Cross-tenant Mailbox Migration.

I have carried out the process in the simplest Only Cloud environment, and I will cover Azure AD Sync and Exchange Hybrid scenarios later. To understand the principles of Migration, you need to understand the principles of Migration in Exchange Server. I will update this part later.

 

https://youtu.be/dNLLk-WNu24

 

 

I have referred to the following technical documentation to write this.

Cross-tenant mailbox migration - Microsoft 365 Enterprise | Microsoft Learn

 

Migration Scenario Diagram

 

 

[Test Environment]

Source Tenant

Tenant: M365x47686041.onmicrosoft.com

Custom domain: wingtiptoys.kr

 

 

Target tenant

Tenant: M365x79002307.onmicrosoft.com

Custom domain: tailspintoys.kr

 

 

Since it is a tenant environment, there is no process for assigning cross-tenant migration licenses.

Without the appropriate license, migration is not possible, so we conducted the test using a shared mailbox.

 

 

Step 1. Prepare the target (destination) tenant by creating the migration application and secret

 

 

Access https://entra.microsoft.com (Target Tenant) -> search for "app registrations" -> click

 

 

New Registration

 

 

 

Enter the information as shown below and then click Register

 

 

Record it as the AppID of the Target Tenant.

 

 

API Permissions -> Add a permission

 

 

APIs my organization uses -> Office 365 Exchange Online -> Office 365 Exchange Online

 

 

Application permissions -> Mailbox.Migration -> Add permission

 

 

Confirm

 

 

Certificates & secrets -> New client secret

 

Description -> Add

 

 

Copy & Record the Value

 

Enterprise Application -> Click the migration app

 

 

Permissions -> Grant admin for Tenant name

 

 

Accept

 

 

Confirm

 

 

After opening a new browser window, access the following URL: (Source Tenant + App ID)

https://login.microsoftonline.com/contoso.onmicrosoft.com/adminconsent?client_id=[application_id_of_the_app_you_just_created]&redirect_uri=https://office.com

#Example
https://login.microsoftonline.com/M365x85148890.onmicrosoft.com/adminconsent?client_id=d8afba35-2ae3-4b42-89f2-8511bfb42bd2&redirect_uri=https://office.com

 

 

Accept

 

 

Step 2. Prepare the target tenant by creating the Exchange Online migration endpoint and organization relationship

Connect Exchange Online Powershell (Target Tenant)

#Enable customization if tenant is dehydrated
Get-OrganizationConfig | select isdehydrated
Enable-OrganizationCustomization
$AppId = "[guid copied from the migrations app]"

$AppId = "d8afba35-2ae3-4b42-89f2-8511bfb42bd2"

 

 

#Create Migration Endpoint

$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, (ConvertTo-SecureString -String "[this is your secret password you saved in the previous steps]" -AsPlainText -Force)
New-MigrationEndpoint -RemoteServer outlook.office.com -RemoteTenant "sourcetenant" -Credentials $Credential -ExchangeRemoteMove:$true -Name "[the name of your migration endpoint]" -ApplicationId $AppId

#Sample
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, (ConvertTo-SecureString -String "1x38Q~7-d-hdD92Ue9Or5A2ilTkO-n7C1p2raaWX" -AsPlainText -Force)
New-MigrationEndpoint -RemoteServer outlook.office.com -RemoteTenant "M365x85148890.onmicrosoft.com" -Credentials $Credential -ExchangeRemoteMove:$true -Name "wingtiptoys" -ApplicationId $AppId

 

 

Looking at the command structure, you can think of the created Migration Application as being connected as follows.

 

 

The endpoint is connected by designating the Remote tenant as the Source tenant.

 

 

#Create Organization Relationship

$sourceTenantId="[tenant id of your trusted partner, where the source mailboxes are]"
$orgrels=Get-OrganizationRelationship
$existingOrgRel = $orgrels | ?{$_.DomainNames -like $sourceTenantId}
If ($null -ne $existingOrgRel)
{
    Set-OrganizationRelationship $existingOrgRel.Name -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability Inbound
}
If ($null -eq $existingOrgRel)
{
    New-OrganizationRelationship "[name of the new organization relationship]" -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability Inbound -DomainNames $sourceTenantId
}
---------------------------------------------------------------
$sourceTenantId="a18c909b-006a-404f-8666-c2ccae261bcd"
$orgrels=Get-OrganizationRelationship
$existingOrgRel = $orgrels | ?{$_.DomainNames -like $sourceTenantId}
If ($null -ne $existingOrgRel)
{
    Set-OrganizationRelationship $existingOrgRel.Name -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability Inbound
}
If ($null -eq $existingOrgRel)
{
    New-OrganizationRelationship "wingtiptoys" -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability Inbound -DomainNames $sourceTenantId
}

 

 

MailboxMoveCapability is understood as specifying the direction of Cross-Tenant Mailbox Migration.

 

 

Copy the Tenant ID from the Source Tenant

 

 

$sourceTenantId="a18c909b-006a-404f-8666-c2ccae261bcd"

 

 

It appears that the migration direction has been enabled as shown below.

 

 

Step3. Prepare the source (current mailbox location) tenant by accepting the migration application and configuring the organization relationship

It can be understood as granting permissions related to app usage in the Source Tenant as shown below.

 

 

Source Tenant -> Exchange Admin Center -> Create Mail-enabled security

 

 

Enter the name

 

 

Add the mailboxes to be migrated to the specified group.

 

 

Assign address -> Complete creation

 

 

Connect Exchange Online Powershell (Source Tenant)

 

 

Create Organization Relationship for the Source Tenant

$targetTenantId="[tenant id of your trusted partner, where the mailboxes are being moved to]"
$appId="[application id of the mailbox migration app you consented to]"
$scope="[name of the mail enabled security group that contains the list of users who are allowed to migrate]"
   $orgrels=Get-OrganizationRelationship
$existingOrgRel = $orgrels | ?{$_.DomainNames -like $targetTenantId}
If ($null -ne $existingOrgRel)
{
    Set-OrganizationRelationship $existingOrgRel.Name -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability RemoteOutbound -OAuthApplicationId $appId -MailboxMovePublishedScopes $scope
}
If ($null -eq $existingOrgRel)
{
    New-OrganizationRelationship "[name of your organization relationship]" -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability RemoteOutbound -DomainNames $targetTenantId -OAuthApplicationId $appId -MailboxMovePublishedScopes $scope
}

 

 

Example

$targetTenantId="27359b9a-645f-424d-b4f2-526903be2546"
$appId="d8afba35-2ae3-4b42-89f2-8511bfb42bd2"
$scope="Migrationgroup"
   $orgrels=Get-OrganizationRelationship
$existingOrgRel = $orgrels | ?{$_.DomainNames -like $targetTenantId}
If ($null -ne $existingOrgRel)
{
    Set-OrganizationRelationship $existingOrgRel.Name -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability RemoteOutbound -OAuthApplicationId $appId -MailboxMovePublishedScopes $scope
}
If ($null -eq $existingOrgRel)
{
    New-OrganizationRelationship "ToTargetTenant" -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability RemoteOutbound -DomainNames $targetTenantId -OAuthApplicationId $appId -MailboxMovePublishedScopes $scope
}

 

 

The RemoteOutbound and Inbound relationship settings have been completed through the Organization Relationship settings of each tenant.

 

 

Step 4.  Create MailUser

Check the properties of the migration mailbox in the Source Tenant

Get-Mailbox -Identity user01 |Select-Object PrimarySMTPAddress,Alias,SamAccountName,FirstName,LastName,DisplayName,Name,ExchangeGuid,ArchiveGuid,LegacyExchangeDn,EmailAddresses

 

 

Create a Mail User in the Target Tenant

New-MailUser -MicrosoftOnlineServicesID User01@tailspintoys.kr -PrimarySmtpAddress User01@tailspintoys.kr -ExternalEmailAddress user01@wingtiptoys.kr -Name User01 -DisplayName User01 -Alias User01 

Set-MailUser -Identity User01 -EmailAddresses @{add="X500:Type the LegacyExchangeDN"} -ExchangeGuid "Type the ExchangeGuid"

#In scenarios where the existing domain needs to be completely removed, enter the onmicrosoft.com address and designate it as the target delivery domain.
Set-MailUser -Identity User01 -EmailAddresses @{add="smtp:user01@M365x47686041.onmicrosoft.com"}

 

 

The attributes were created to map as follows.

 

 

Check the migration connection status with the following command.

Test-MigrationServerAvailability -Endpoint "wingtiptoys" -TestMailbox "user01@tailspintoys.kr"

 

 

Step 5. Migration

Migration -> Add Migration batch

 

 

Migration to Exchange Online -> Next

 

 

Cross tenant migration -> Next

 

 

Next

 

 

Select migration endpoint ->Next

 

 

Import CSV file

 

 

Create a CSV with the Target Email Address and proceed with the import.

 

 

Enter target delivery domain

 

 

Save

 

 

Synchronization proceeds as shown below.

 

 

 

After checking the license assignment status, click Complete migration batch. ->

If the migration is complete, remove the batch.

 

 

You can confirm the migrated mailboxes as shown below.

 

 

And the existing Source Mailbox is changed to a Mail User.

Since the External Address is the Target Tenant address, any emails received after the transition will be forwarded to the Target Tenant.

 

 

The overall migration flow is not significantly different from Exchange hybrid or Cross-Forest.

반응형

+ Recent posts