Hello Curtis,
Powershell
$API = $null;
$APIHost = 'localhost';
$HTTPS = $false;
$API = @{
authUserName = 'admin'
authPassword = 'admin'
Method = 'POST'
ContentType = 'application/json'
URI = 'http'+$(if($HTTPS -eq $true){'s'})+'://'+$APIHost+'/'
ShowAuthData = $true
rootAPIURI = 'http'+$(if($HTTPS -eq $true){'s'})+'://'+$APIHost+'/Documentation/api#/reference/SmarterMail.Web.Controllers.'
debug = $false
};
function PrimaryAuth {
<#
.Synopsis
Primary API auth call
.DESCRIPTION
Primary Auth Call that will add the appropriate header s for refreshing, calling headers
.EXAMPLE
PrimaryAuth
.EXAMPLE
$r=(PrimaryAuth -twoFactorCode '' -retrieveAutoLoginToken $true );
Start-Process -FilePath Chrome -ArgumentList ($r.autoLoginUrl);
#>
[OutputType([Object])]
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false)]
[string]$twoFactorCode,
[Parameter(Mandatory=$false)]
[ValidateSet($true,$false)]
[Boolean]$retrieveAutoLoginToken,
[Parameter(Mandatory=$false)]
[string]$autoLoginToken
)
$APIAuth = @{};
$APIAuth = @{
Uri=('http' + $(if ($HTTPS -eq $true ) {'s'}) + '://' + $APIHost + '/api/v1/auth/authenticate-user');
Body =@{
username=$API.authUserName
password=$API.authPassword
language=$null
twoFactorCode=$twoFactorCode
retrieveAutoLoginToken=$retrieveAutoLoginToken
}
};
$Auth = Invoke-RestMethod -Uri $APIAuth.Uri -ContentType $API.ContentType -Body ($APIAuth.Body|ConvertTo-Json -Compress) -Method POST;
# SERVER ADMIN AUTH TOKEN
$API.Remove('Headers');
$API.Add('Headers', @{ 'Authorization' = "Bearer $($Auth.accessToken)" });
# REFRESH
$API.Remove('Refresh');
$API.Add('Refresh' , @{"token" = $($Auth.refreshToken)});
# EXPIRATION
if ( $Auth.accessTokenExpiration ) {
$API.Remove('accessTokenExpiration');
[DateTime]$ATExp = $Auth.accessTokenExpiration;
$API.Add('accessTokenExpiration', $ATExp);
}
if ($API.ShowAuthData) {return $Auth};
};
function impersonate_user {
<#
.Synopsis
Impersonate a user
.DESCRIPTION
.EXAMPLE
This example will work with the newer builds
ImpersonateUser 'admin@domain.tld'
This example works with the Pre BETA builds
BETA went live with this version --> Build 8495 (Apr 5, 2023)
ImpersonateUser 'admin@domain.tld' -Beta
.EXAMPLE
$r=(PrimaryAuth -twoFactorCode '' -retrieveAutoLoginToken $true );
Start-Process -FilePath Chrome -ArgumentList ($r.autoLoginUrl);
.NOTES
The trigger used to be BETA and now it is preBeta. I Added Beta as
as aliase to work with older code. This was changed as it was orginally
added when the code was still in Beta but is it now in the Public Branch.
#>
[CmdletBinding()]
[Alias("ImpersonateUser")]
Param (
[Parameter(Mandatory=$true)][string]$user_email,
[Parameter()][alias('beta')][switch]$preBeta
)
if (!$preBeta) {
$URI = $('http' + $(if ($HTTPS -eq $true ) {'s'}) + '://' + $APIHost + '/api/v1/settings/domain/impersonate-user/' )
$Impersonate = Invoke-RestMethod -Method POST -Uri $URI -ContentType $API.ContentType -Headers $API.Headers -Body "{`"email`":`"$user_email`"}"
} else {
$URI = $('http' + $(if ($HTTPS -eq $true ) {'s'}) + '://' + $APIHost + '/api/v1/settings/domain/impersonate-user/' + $user_email )
$Impersonate = Invoke-RestMethod -Method POST -Uri $URI -ContentType $API.ContentType -Headers $API.Headers
}
# IMPERSONATE AUTH TOKEN
$API.Remove('HeaderImpersonate')
$API.Add('HeaderImpersonate', @{ 'Authorization' = "Bearer $($Impersonate.impersonateAccessToken)" })
$API.ImpersonateObject=$Impersonate;
# REFRESH
$API.Remove('impersonateRefresh');
$API.Add('impersonateRefresh' , @{"token" = $($Impersonate.impersonateRefreshToken)});
# EXPIRATION
$API.Remove('impersonateAccessTokenExpiration');
[DateTime]$ATExp = $Impersonate.impersonateAccessTokenExpiration;
$API.Add('impersonateAccessTokenExpiration', $ATExp);
if ($API.ShowAuthData) {return $Impersonate;}
};
function UpdateURImethod {
<#
.Synopsis
Pass in new API Method and new API URI
.DESCRIPTION
This can be called at teh beigging of any new call to update the $API array
with a new METHOD and a new URI
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,
HelpMessage="GET or POST method")]
[ValidateNotNullOrEmpty()]
[ValidateSet("get", "post")]
[String]$a,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]$b
)
$b = $b.TrimStart('/');
$API.uri = 'http' + $(if ($HTTPS -eq $true ) {'s'}) + '://' + $APIHost + '/' + $b; $API.Method = $a;
};
function ConnectPrimary {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false)]
[String]$json_body,
[Parameter(Mandatory=$false)]
[String]$filePath
)
Begin {
$params = @{
Uri = $API.Uri
ContentType = $API.ContentType
Method = $API.Method
Headers = $API.Headers
}
}
Process {
if ($json_body) {$params.Add("Body", $json_body)}
if ($filePath) {$params.Add("OutFile", $filePath)}
try {
$call = Invoke-RestMethod @params
}
catch {
$params
}
}
end { return $call }
}
function ConnectImpersonate {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false)]
[ValidateScript({
try {
$jsonObject = $null
return ($_ | ConvertFrom-Json)
}
catch {throw "Invalid JSON format for the body."}
})]
[String]$json_body,
[Parameter(Mandatory=$false)]
[ValidateScript({
if (Test-Path -Path $_ -PathType Leaf) {
return $true
} else {throw "Invalid file path."}
})]
[String]$filePath
)
begin {
$params = @{
Uri = $API.Uri
ContentType = $API.ContentType
Method = $API.Method
Headers = $API.HeaderImpersonate
}
}
process {
if ($json_body) {$params.Add("Body", $json_body)}
if ($filePath) {$params.Add("OutFile", $filePath)}
try {
$call = Invoke-RestMethod @params
}
catch {
$Error[0];$params
}
}
end { return $call }
}
PrimaryAuth;
ImpersonateUser 'admin@ascholz.io';
UpdateURImethod 'POST' 'api/v1/mail/message-put'
for ($i=0;$i -le 2;$i++ ) {
$MSG = @{
to = "all@ascholz.io"
cc = ""
bcc = ""
#date = 1679957034265
from = "admin@ascholz.io"
replyTo = "admin@ascholz.io"
subject = "!!! Test MSG $((Get-Date).ToString("HH:mm:ss:ffff"))"
messageHTML = 'Test Message Here'
ownerEmailAddress = ""
actions = @{}
readReceiptRequested = $false
deliveryReceiptRequested = $false
priority = 1
inlineToRemove = @()
selectedFrom = ":admin@ascholz.io"
}
ConnectImpersonate ($MSG|ConvertTo-Json -Compress)
sleep -Seconds 1;
}
Python
full code with the appropriate methods from the functions file.
import requests
import json
import logging
from logging.handlers import TimedRotatingFileHandler, RotatingFileHandler
from typing import Literal, Optional
from pprint import pprint
from datetime import datetime, timezone
from colorama import Fore, Back, Style, init
import random
class API:
ContentType = 'application/json'
# Primary auth headers
headers = {'Authorization': ''}
refresh = {'token': ''}
accessToken = None
refreshToken = None
accessTokenExpiration = None
# Impersonation headers
impersonateObject = None
HeaderImpersonate = {'Authorization': ''}
impersonateRefresh = {'token': ''}
impersonateRefreshToken = None
impersonateAccessTokenExpiration = None
impersonateAccessToken = None
def __init__(self, u='admin', p='admin', h='sup-ascholz.st.local', s=False, ShowAuthData: bool = False, debug: bool = False):
self.username = u
self.password = p
self.host = h
self.secure = s
self.uri = f"http{'s' if s else ''}://{self.host}/"
self.ShowAuthData = ShowAuthData
self.debug = debug
self.authenticate()
self.get_global_mail_settings()
def authenticate(self):
"""
Authenticates and retrieves access and refresh tokens for API access.
"""
authUri = f"{self.uri}api/v1/auth/authenticate-user"
auth_obj = {'username': self.username, 'password': self.password}
headers = {'Content-Type': self.ContentType}
response = requests.post(authUri, json=auth_obj, headers=headers)
if response.status_code == 200:
auth_data = response.json()
self.accessToken = auth_data.get('accessToken')
self.refreshToken = auth_data.get('refreshToken')
self.accessTokenExpiration = auth_data.get('accessTokenExpiration')
self.headers['Authorization'] = f"Bearer {self.accessToken}"
self.refresh['token'] = self.refreshToken
if self.ShowAuthData:
print("Authentication Successful:", auth_data)
else:
print(f"{Fore.GREEN}Authentication Successful!{Style.RESET_ALL} {self.host}")
else:
print(f"Error: Received status code {response.status_code}")
print("Response content:", response.text)
def refresh_auth(self):
"""
Refreshes the authentication token using the stored refresh token.
"""
_uri = 'api/v1/auth/refresh-token'
_body = self.refresh
if self.debug: print(Fore.MAGENTA + f'accessTokenExpiration: {self.accessTokenExpiration}' + Style.RESET_ALL)
_results = requests.post(url=_uri, json=_body, headers=self.headers)
self.accessToken = _results.json()['accessToken']
self.refreshToken = _results.json()['refreshToken']
self.accessTokenExpiration = _results.json()['accessTokenExpiration']
self.headers['Authorization'] = ("Bearer " + self.accessToken)
self.refresh['token'] = self.refreshToken
if self.ShowAuthData:
print("Authentication Successful:", _results.json())
def impersonate_user(self, user_email, preBeta=False):
if preBeta:
uri = f"{self.uri}api/v1/settings/domain/impersonate-user/{user_email}"
response = requests.post(uri, headers=self.headers)
else:
uri = f"{self.uri}api/v1/settings/domain/impersonate-user/"
payload = {"email": user_email}
response = requests.post(uri, headers=self.headers, json=payload)
if response.status_code == 200:
impersonate_data = response.json()
# Update the API class instance with impersonation tokens and expiration
self.HeaderImpersonate = {'Authorization': f"Bearer {impersonate_data['impersonateAccessToken']}"}
self.impersonateRefresh = {'token': impersonate_data['impersonateRefreshToken']}
self.impersonateAccessTokenExpiration = impersonate_data.get('impersonateAccessTokenExpiration')
self.impersonateRefreshTokenExpiration = impersonate_data.get('impersonateRefreshTokenExpiration')
self.impersonateObject = impersonate_data # Store the full response if needed
if self.ShowAuthData:
print("Impersonate Data:", impersonate_data) # Show the auth data if required
return impersonate_data # Optionally return the data if further use is required
else:
print(f"Error: Received status code {response.status_code}")
print("Response content:", response.text)
return None
def cImpersonate(api_class, method, uri_path, json_body=None):
uri = api_class.uri + uri_path
if json_body:
# print('JSON body passed')
if str(method).upper() == "POST":
c_primary_data = requests.post(uri, headers=api_class.HeaderImpersonate, json=json_body)
elif str(method).upper() == "GET":
c_primary_data = requests.get(uri, headers=api_class.HeaderImpersonate, json=json_body)
else:
return print("The METHOD needs to be either GET or POST")
elif not json_body:
# print('JSON body NOT passed')
if str(method).upper() == "POST":
c_primary_data = requests.post(uri, headers=api_class.HeaderImpersonate)
elif str(method).upper() == "GET":
c_primary_data = requests.get(uri, headers=api_class.HeaderImpersonate)
else:
return print("The METHOD needs to be either GET or POST")
return c_primary_data
API_connection = API()
API_connection.impersonate_user(user_email='admin@ascholz.io')
MSG = {
'to': "all@ascholz.io",
'cc': "",
'bcc': "",
'from': "admin@ascholz.io",
'replyTo': "admin@ascholz.io",
'subject': "!!! Test MSG !!!",
'messageHTML': 'Test Message Here',
'ownerEmailAddress': "",
'actions': {},
'readReceiptRequested': False,
'deliveryReceiptRequested': False,
'priority': 1,
'inlineToRemove': [],
'selectedFrom': ":admin@ascholz.io"
}
results = cImpersonate(API_connection, 'POST', 'api/v1/mail/message-put', json_body=MSG)
results.status_code
ASP (Converted from Powershell by ChatGPT This has NOT been tested)
<%
Option Explicit
Dim API, APIHost, HTTPS, authUserName, authPassword
APIHost = "localhost"
HTTPS = False
authUserName = "admin"
authPassword = "admin"
' Initialize API object
Set API = CreateObject("Scripting.Dictionary")
API.Add "authUserName", authUserName
API.Add "authPassword", authPassword
API.Add "Method", "POST"
API.Add "ContentType", "application/json"
API.Add "URI", "http" & IIf(HTTPS, "s", "") & "://" & APIHost & "/"
API.Add "ShowAuthData", True
API.Add "rootAPIURI", "http" & IIf(HTTPS, "s", "") & "://" & APIHost & "/Documentation/api#/reference/SmarterMail.Web.Controllers."
' Function for primary authentication
Function PrimaryAuth(twoFactorCode, retrieveAutoLoginToken)
Dim authUri, authBody, authToken, xhr
authUri = "http" & IIf(HTTPS, "s", "") & "://" & APIHost & "/api/v1/auth/authenticate-user"
authBody = "{""username"":""" & API.Item("authUserName") & """, ""password"":""" & API.Item("authPassword") & """, ""language"":null, ""twoFactorCode"":""" & twoFactorCode & """, ""retrieveAutoLoginToken"":" & LCase(CStr(retrieveAutoLoginToken)) & "}"
Set xhr = Server.CreateObject("MSXML2.ServerXMLHTTP")
xhr.Open "POST", authUri, False
xhr.setRequestHeader "Content-Type", API.Item("ContentType")
xhr.Send authBody
If xhr.Status = 200 Then
Dim response
response = xhr.responseText
' Process and extract tokens from response
' For brevity, assuming JSON is parsed to extract accessToken, refreshToken, and accessTokenExpiration
API.Remove "Headers"
API.Add "Headers", "Authorization: Bearer " & ExtractJsonValue(response, "accessToken")
Else
Response.Write "Failed to authenticate. Status: " & xhr.Status
End If
Set xhr = Nothing
End Function
' Function to send an email message
Function SendEmailMessage(toEmail, fromEmail, subject, messageHTML)
Dim msgUri, msgBody, xhr
msgUri = API.Item("URI") & "api/v1/mail/message-put"
msgBody = "{""to"":""" & toEmail & """, ""from"":""" & fromEmail & """, ""subject"":""" & subject & """, ""messageHTML"":""" & messageHTML & """}"
Set xhr = Server.CreateObject("MSXML2.ServerXMLHTTP")
xhr.Open "POST", msgUri, False
xhr.setRequestHeader "Content-Type", API.Item("ContentType")
xhr.setRequestHeader "Authorization", API.Item("Headers")
xhr.Send msgBody
If xhr.Status = 200 Then
Response.Write "Email sent successfully.<br>"
Else
Response.Write "Failed to send email. Status: " & xhr.Status & "<br>"
End If
Set xhr = Nothing
End Function
' Function to extract JSON values (simplified JSON parsing)
Function ExtractJsonValue(jsonString, key)
Dim posKey, posValue, endPos
posKey = InStr(jsonString, """" & key & """")
If posKey > 0 Then
posValue = InStr(posKey, jsonString, ":") + 1
endPos = InStr(posValue, jsonString, ",")
If endPos = 0 Then endPos = InStr(posValue, jsonString, "}")
ExtractJsonValue = Mid(jsonString, posValue, endPos - posValue)
ExtractJsonValue = Replace(Replace(ExtractJsonValue, """", ""), "}", "")
Else
ExtractJsonValue = ""
End If
End Function
' Authenticate and send messages in a loop
Call PrimaryAuth("", "true")
Dim i
For i = 0 To 2
Dim toEmail, fromEmail, subject, messageHTML
toEmail = "all@ascholz.io"
fromEmail = "admin@ascholz.io"
subject = "!!! Test MSG " & Time
messageHTML = "Test Message Here"
Call SendEmailMessage(toEmail, fromEmail, subject, messageHTML)
' Sleep for 1 second between requests
Call Sleep(1)
Next
' Sleep function
Sub Sleep(seconds)
Dim objShell
Set objShell = Server.CreateObject("WScript.Shell")
objShell.Run "cmd /c ping -n " & seconds + 1 & " 127.0.0.1>nul", 0, True
Set objShell = Nothing
End Sub
%>