// Copyright 2022 Luca Casonato. All rights reserved. MIT license. /** * Gmail Postmaster Tools API Client for Deno * ========================================== * * The Postmaster Tools API is a RESTful API that provides programmatic access to email traffic metrics (like spam reports, delivery errors etc) otherwise available through the Gmail Postmaster Tools UI currently. * * Docs: https://developers.google.com/workspace/gmail/postmaster * Source: https://googleapis.deno.dev/v1/gmailpostmastertools:v2.ts */ import { auth, CredentialsClient, GoogleAuth, request } from "/_/base@v1/mod.ts"; export { auth, GoogleAuth }; export type { CredentialsClient }; /** * The Postmaster Tools API is a RESTful API that provides programmatic access * to email traffic metrics (like spam reports, delivery errors etc) otherwise * available through the Gmail Postmaster Tools UI currently. */ export class GmailPostmasterTools { #client: CredentialsClient | undefined; #baseUrl: string; constructor(client?: CredentialsClient, baseUrl: string = "https://gmailpostmastertools.googleapis.com/") { this.#client = client; this.#baseUrl = baseUrl; } /** * Retrieves a list of domain statistics for a given domain and time period. * Returns statistics only for dates where data is available. Returns * PERMISSION_DENIED if you don't have permission to access DomainStats for * the domain. * * @param parent Required. The parent resource name where the stats are queried. Format: domains/{domain} */ async domainsDomainStatsQuery(parent: string, req: QueryDomainStatsRequest): Promise { const url = new URL(`${this.#baseUrl}v2/${ parent }/domainStats:query`); const body = JSON.stringify(req); const data = await request(url.href, { client: this.#client, method: "POST", body, }); return deserializeQueryDomainStatsResponse(data); } /** * Retrieves detailed information about a domain registered by you. Returns * NOT_FOUND if the domain is not registered by you. Domain represents the * metadata of a domain that has been registered within the system and linked * to a user. * * @param name Required. The resource name of the domain. Format: `domains/{domain_name}`, where domain_name is the fully qualified domain name (i.e., mymail.mydomain.com). */ async domainsGet(name: string): Promise { const url = new URL(`${this.#baseUrl}v2/${ name }`); const data = await request(url.href, { client: this.#client, method: "GET", }); return deserializeDomain(data); } /** * Retrieves the compliance status for a given domain. Returns * PERMISSION_DENIED if you don't have permission to access compliance status * for the domain. * * @param name Required. The resource name of the domain's compliance status to retrieve. Format: `domains/{domain_id}/complianceStatus`. */ async domainsGetComplianceStatus(name: string): Promise { const url = new URL(`${this.#baseUrl}v2/${ name }`); const data = await request(url.href, { client: this.#client, method: "GET", }); return data as DomainComplianceStatus; } /** * Retrieves a list of all domains registered by you, along with their * corresponding metadata. The order of domains in the response is unspecified * and non-deterministic. Newly registered domains will not necessarily be * added to the end of this list. * */ async domainsList(opts: DomainsListOptions = {}): Promise { const url = new URL(`${this.#baseUrl}v2/domains`); if (opts.pageSize !== undefined) { url.searchParams.append("pageSize", String(opts.pageSize)); } if (opts.pageToken !== undefined) { url.searchParams.append("pageToken", String(opts.pageToken)); } const data = await request(url.href, { client: this.#client, method: "GET", }); return deserializeListDomainsResponse(data); } /** * Executes a batch of QueryDomainStats requests for multiple domains. * Returns PERMISSION_DENIED if you don't have permission to access * DomainStats for any of the requested domains. * */ async domainStatsBatchQuery(req: BatchQueryDomainStatsRequest): Promise { const url = new URL(`${this.#baseUrl}v2/domainStats:batchQuery`); const body = JSON.stringify(req); const data = await request(url.href, { client: this.#client, method: "POST", body, }); return deserializeBatchQueryDomainStatsResponse(data); } } /** * Specifies the base metric to query, which can be a predefined standard * metric or a user-defined custom metric (if supported in the future). */ export interface BaseMetric { /** * A predefined standard metric. */ standardMetric?: | "STANDARD_METRIC_UNSPECIFIED" | "FEEDBACK_LOOP_ID" | "FEEDBACK_LOOP_SPAM_RATE" | "SPAM_RATE" | "AUTH_SUCCESS_RATE" | "TLS_ENCRYPTION_MESSAGE_COUNT" | "TLS_ENCRYPTION_RATE" | "DELIVERY_ERROR_COUNT" | "DELIVERY_ERROR_RATE"; } /** * Request message for BatchQueryDomainStats. */ export interface BatchQueryDomainStatsRequest { /** * Required. A list of individual query requests. Each request can be for a * different domain. A maximum of 100 requests can be included in a single * batch. */ requests?: QueryDomainStatsRequest[]; } /** * Response message for BatchQueryDomainStats. */ export interface BatchQueryDomainStatsResponse { /** * A list of responses, one for each query in the * BatchQueryDomainStatsRequest. The order of responses will correspond to the * order of requests. */ results?: BatchQueryDomainStatsResult[]; } function serializeBatchQueryDomainStatsResponse(data: any): BatchQueryDomainStatsResponse { return { ...data, results: data["results"] !== undefined ? data["results"].map((item: any) => (serializeBatchQueryDomainStatsResult(item))) : undefined, }; } function deserializeBatchQueryDomainStatsResponse(data: any): BatchQueryDomainStatsResponse { return { ...data, results: data["results"] !== undefined ? data["results"].map((item: any) => (deserializeBatchQueryDomainStatsResult(item))) : undefined, }; } /** * Represents the result of a single QueryDomainStatsRequest within a batch. */ export interface BatchQueryDomainStatsResult { /** * The error status if the individual query failed. */ error?: Status; /** * The successful response for the individual query. */ response?: QueryDomainStatsResponse; } function serializeBatchQueryDomainStatsResult(data: any): BatchQueryDomainStatsResult { return { ...data, response: data["response"] !== undefined ? serializeQueryDomainStatsResponse(data["response"]) : undefined, }; } function deserializeBatchQueryDomainStatsResult(data: any): BatchQueryDomainStatsResult { return { ...data, response: data["response"] !== undefined ? deserializeQueryDomainStatsResponse(data["response"]) : undefined, }; } /** * Data for a single row of the compliance status table. */ export interface ComplianceRowData { /** * The compliance requirement. */ requirement?: | "COMPLIANCE_REQUIREMENT_UNSPECIFIED" | "SPF" | "DKIM" | "SPF_AND_DKIM" | "DMARC_POLICY" | "DMARC_ALIGNMENT" | "MESSAGE_FORMATTING" | "DNS_RECORDS" | "ENCRYPTION" | "USER_REPORTED_SPAM_RATE" | "ONE_CLICK_UNSUBSCRIBE" | "HONOR_UNSUBSCRIBE"; /** * The compliance status for the requirement. */ status?: ComplianceStatus; } /** * The status of a sender compliance requirement. */ export interface ComplianceStatus { /** * Output only. The compliance status. */ readonly status?: | "STATE_UNSPECIFIED" | "COMPLIANT" | "NEEDS_WORK"; } /** * Represents a whole or partial calendar date, such as a birthday. The time of * day and time zone are either specified elsewhere or are insignificant. The * date is relative to the Gregorian Calendar. This can represent one of the * following: * A full date, with non-zero year, month, and day values. * A * month and day, with a zero year (for example, an anniversary). * A year on * its own, with a zero month and a zero day. * A year and month, with a zero * day (for example, a credit card expiration date). Related types: * * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp */ export interface Date { /** * Day of a month. Must be from 1 to 31 and valid for the year and month, or * 0 to specify a year by itself or a year and month where the day isn't * significant. */ day?: number; /** * Month of a year. Must be from 1 to 12, or 0 to specify a year without a * month and day. */ month?: number; /** * Year of the date. Must be from 1 to 9999, or 0 to specify a date without a * year. */ year?: number; } /** * A set of specific dates. */ export interface DateList { /** * Required. The list of specific dates for which to retrieve data. */ dates?: Date[]; } /** * A single date range defined by a start and end date. */ export interface DateRange { /** * Required. The inclusive end date of the date range. */ end?: Date; /** * Required. The inclusive start date of the date range. */ start?: Date; } /** * A set of date ranges. */ export interface DateRanges { /** * Required. The list of date ranges for which to retrieve data. */ dateRanges?: DateRange[]; } /** * Information about a domain registered by the user. */ export interface Domain { /** * Output only. Immutable. The timestamp at which the domain was added to the * user's account. */ readonly createTime?: Date; /** * The timestamp at which the domain was last verified by the user. */ lastVerifyTime?: Date; /** * Identifier. The resource name of the domain. Format: * `domains/{domain_name}`, where domain_name is the fully qualified domain * name (i.e., mymail.mydomain.com). */ name?: string; /** * Output only. User's permission of this domain. */ readonly permission?: | "PERMISSION_UNSPECIFIED" | "READER" | "OWNER" | "NONE"; /** * Output only. Information about a user's verification history and * properties for the domain. */ readonly verificationState?: | "VERIFICATION_STATE_UNSPECIFIED" | "UNVERIFIED" | "VERIFIED"; } function serializeDomain(data: any): Domain { return { ...data, lastVerifyTime: data["lastVerifyTime"] !== undefined ? data["lastVerifyTime"].toISOString() : undefined, }; } function deserializeDomain(data: any): Domain { return { ...data, createTime: data["createTime"] !== undefined ? new Date(data["createTime"]) : undefined, lastVerifyTime: data["lastVerifyTime"] !== undefined ? new Date(data["lastVerifyTime"]) : undefined, }; } /** * Compliance data for a given domain. */ export interface DomainComplianceData { /** * Domain that this data is for. */ domainId?: string; /** * Unsubscribe honoring compliance verdict. */ honorUnsubscribeVerdict?: HonorUnsubscribeVerdict; /** * One-click unsubscribe compliance verdict. */ oneClickUnsubscribeVerdict?: OneClickUnsubscribeVerdict; /** * Data for each of the rows of the table. Each message contains all the data * that backs a single row. */ rowData?: ComplianceRowData[]; } /** * Compliance status for a domain. */ export interface DomainComplianceStatus { /** * Compliance data for the registrable domain part of the domain in `name`. * For example, if `name` is `domains/example.com/complianceStatus`, this * field contains compliance data for `example.com`. */ complianceData?: DomainComplianceData; /** * Identifier. The resource name of the domain's compliance status. Format: * `domains/{domain_id}/complianceStatus`. */ name?: string; /** * Compliance data calculated specifically for the subdomain in `name`. This * field is only populated if the domain in `name` is a subdomain that differs * from its registrable domain (e.g., `sub.example.com`), and if compliance * data is available for that specific subdomain. */ subdomainComplianceData?: DomainComplianceData; } /** * Additional options for GmailPostmasterTools#domainsList. */ export interface DomainsListOptions { /** * Optional. Requested page size. Server may return fewer domains than * requested. If unspecified, the default value for this field is 10. The * maximum value for this field is 200. */ pageSize?: number; /** * Optional. The next_page_token value returned from a previous List request, * if any. */ pageToken?: string; } /** * Email statistics for a domain for a specified time period or date. */ export interface DomainStat { /** * Optional. The specific date for these stats, if granularity is DAILY. This * field is populated if the QueryDomainStatsRequest specified a DAILY * aggregation granularity. */ date?: Date; /** * The user-defined name from MetricDefinition.name in the request, used to * correlate this result with the requested metric. */ metric?: string; /** * Output only. The resource name of the DomainStat resource. Format: * domains/{domain}/domainStats/{domain_stat} The `{domain_stat}` segment is * an opaque, server-generated ID. We recommend using the `metric` field to * identify queried metrics instead of parsing the name. */ readonly name?: string; /** * The value of the corresponding metric. */ value?: StatisticValue; } function serializeDomainStat(data: any): DomainStat { return { ...data, value: data["value"] !== undefined ? serializeStatisticValue(data["value"]) : undefined, }; } function deserializeDomainStat(data: any): DomainStat { return { ...data, value: data["value"] !== undefined ? deserializeStatisticValue(data["value"]) : undefined, }; } /** * Compliance verdict for whether a sender meets the unsubscribe honoring * compliance requirement. */ export interface HonorUnsubscribeVerdict { /** * The specific reason for the compliance verdict. Must be empty if the * status is compliant. */ reason?: | "REASON_UNSPECIFIED" | "NOT_HONORING" | "NOT_HONORING_TOO_FEW_CAMPAIGNS" | "NOT_HONORING_TOO_MANY_CAMPAIGNS"; /** * The compliance status. */ status?: ComplianceStatus; } /** * Response message for ListDomains. */ export interface ListDomainsResponse { /** * The domains that have been registered by the user. */ domains?: Domain[]; /** * Token to retrieve the next page of results, or empty if there are no more * results in the list. */ nextPageToken?: string; } function serializeListDomainsResponse(data: any): ListDomainsResponse { return { ...data, domains: data["domains"] !== undefined ? data["domains"].map((item: any) => (serializeDomain(item))) : undefined, }; } function deserializeListDomainsResponse(data: any): ListDomainsResponse { return { ...data, domains: data["domains"] !== undefined ? data["domains"].map((item: any) => (deserializeDomain(item))) : undefined, }; } /** * Defines a specific metric to query, including a user-defined name, the base * metric type, and optional filters. */ export interface MetricDefinition { /** * Required. The underlying metric to query. */ baseMetric?: BaseMetric; /** * Optional. Optional filters to apply to the metric. */ filter?: string; /** * Required. The user-defined name for this metric. This name will be used as * the key for this metric's value in the response. */ name?: string; } /** * Compliance verdict for whether a sender meets the one-click unsubscribe * compliance requirement. */ export interface OneClickUnsubscribeVerdict { /** * The specific reason for the compliance verdict. Must be empty if the * status is compliant. */ reason?: | "REASON_UNSPECIFIED" | "NO_UNSUB_GENERAL" | "NO_UNSUB_SPAM_REPORTS" | "NO_UNSUB_PROMO_SPAM_REPORTS"; /** * The compliance status. */ status?: ComplianceStatus; } /** * Request message for QueryDomainStats. */ export interface QueryDomainStatsRequest { /** * Optional. The granularity at which to aggregate the statistics. If * unspecified, defaults to DAILY. */ aggregationGranularity?: | "AGGREGATION_GRANULARITY_UNSPECIFIED" | "DAILY" | "OVERALL"; /** * Required. The specific metrics to query. You can define a custom name for * each metric, which will be used in the response. */ metricDefinitions?: MetricDefinition[]; /** * Optional. The maximum number of DomainStats resources to return in the * response. The server may return fewer than this value. If unspecified, a * default value of 10 will be used. The maximum value is 200. */ pageSize?: number; /** * Optional. The next_page_token value returned from a previous List request, * if any. If the aggregation granularity is DAILY, the page token will be the * encoded date + "/" + metric name. If the aggregation granularity is * OVERALL, the page token will be the encoded metric name. */ pageToken?: string; /** * Required. The parent resource name where the stats are queried. Format: * domains/{domain} */ parent?: string; /** * Required. The time range or specific dates for which to retrieve the * metrics. */ timeQuery?: TimeQuery; } /** * Response message for QueryDomainStats. */ export interface QueryDomainStatsResponse { /** * The list of domain statistics. Each DomainStat object contains the value * for a metric requested in the QueryDomainStatsRequest. */ domainStats?: DomainStat[]; /** * Token to retrieve the next page of results, or empty if there are no more * results in the list. */ nextPageToken?: string; } function serializeQueryDomainStatsResponse(data: any): QueryDomainStatsResponse { return { ...data, domainStats: data["domainStats"] !== undefined ? data["domainStats"].map((item: any) => (serializeDomainStat(item))) : undefined, }; } function deserializeQueryDomainStatsResponse(data: any): QueryDomainStatsResponse { return { ...data, domainStats: data["domainStats"] !== undefined ? data["domainStats"].map((item: any) => (deserializeDomainStat(item))) : undefined, }; } /** * The actual value of a statistic. */ export interface StatisticValue { /** * Double value. */ doubleValue?: number; /** * Float value. */ floatValue?: number; /** * Integer value. */ intValue?: bigint; /** * List of string values. */ stringList?: StringList; /** * String value. */ stringValue?: string; } function serializeStatisticValue(data: any): StatisticValue { return { ...data, intValue: data["intValue"] !== undefined ? String(data["intValue"]) : undefined, }; } function deserializeStatisticValue(data: any): StatisticValue { return { ...data, intValue: data["intValue"] !== undefined ? BigInt(data["intValue"]) : undefined, }; } /** * The `Status` type defines a logical error model that is suitable for * different programming environments, including REST APIs and RPC APIs. It is * used by [gRPC](https://github.com/grpc). Each `Status` message contains three * pieces of data: error code, error message, and error details. You can find * out more about this error model and how to work with it in the [API Design * Guide](https://cloud.google.com/apis/design/errors). */ export interface Status { /** * The status code, which should be an enum value of google.rpc.Code. */ code?: number; /** * A list of messages that carry the error details. There is a common set of * message types for APIs to use. */ details?: { [key: string]: any }[]; /** * A developer-facing error message, which should be in English. Any * user-facing error message should be localized and sent in the * google.rpc.Status.details field, or localized by the client. */ message?: string; } /** * Represents a list of strings. */ export interface StringList { /** * The string values. */ values?: string[]; } /** * The date ranges or specific dates for which you want to retrieve data. */ export interface TimeQuery { /** * A list of specific dates. */ dateList?: DateList; /** * A list of date ranges. */ dateRanges?: DateRanges; }