1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package ses
4
5import (
6	"context"
7	"fmt"
8	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
9	"github.com/aws/aws-sdk-go-v2/aws/signer/v4"
10	"github.com/aws/aws-sdk-go-v2/service/ses/types"
11	"github.com/aws/smithy-go/middleware"
12	smithytime "github.com/aws/smithy-go/time"
13	smithyhttp "github.com/aws/smithy-go/transport/http"
14	smithywaiter "github.com/aws/smithy-go/waiter"
15	"github.com/jmespath/go-jmespath"
16	"time"
17)
18
19// Given a list of identities (email addresses and/or domains), returns the
20// verification status and (for domain identities) the verification token for each
21// identity. The verification status of an email address is "Pending" until the
22// email address owner clicks the link within the verification email that Amazon
23// SES sent to that address. If the email address owner clicks the link within 24
24// hours, the verification status of the email address changes to "Success". If the
25// link is not clicked within 24 hours, the verification status changes to
26// "Failed." In that case, if you still want to verify the email address, you must
27// restart the verification process from the beginning. For domain identities, the
28// domain's verification status is "Pending" as Amazon SES searches for the
29// required TXT record in the DNS settings of the domain. When Amazon SES detects
30// the record, the domain's verification status changes to "Success". If Amazon SES
31// is unable to detect the record within 72 hours, the domain's verification status
32// changes to "Failed." In that case, if you still want to verify the domain, you
33// must restart the verification process from the beginning. This operation is
34// throttled at one request per second and can only get verification attributes for
35// up to 100 identities at a time.
36func (c *Client) GetIdentityVerificationAttributes(ctx context.Context, params *GetIdentityVerificationAttributesInput, optFns ...func(*Options)) (*GetIdentityVerificationAttributesOutput, error) {
37	if params == nil {
38		params = &GetIdentityVerificationAttributesInput{}
39	}
40
41	result, metadata, err := c.invokeOperation(ctx, "GetIdentityVerificationAttributes", params, optFns, addOperationGetIdentityVerificationAttributesMiddlewares)
42	if err != nil {
43		return nil, err
44	}
45
46	out := result.(*GetIdentityVerificationAttributesOutput)
47	out.ResultMetadata = metadata
48	return out, nil
49}
50
51// Represents a request to return the Amazon SES verification status of a list of
52// identities. For domain identities, this request also returns the verification
53// token. For information about verifying identities with Amazon SES, see the
54// Amazon SES Developer Guide
55// (https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-addresses-and-domains.html).
56type GetIdentityVerificationAttributesInput struct {
57
58	// A list of identities.
59	//
60	// This member is required.
61	Identities []string
62}
63
64// The Amazon SES verification status of a list of identities. For domain
65// identities, this response also contains the verification token.
66type GetIdentityVerificationAttributesOutput struct {
67
68	// A map of Identities to IdentityVerificationAttributes objects.
69	//
70	// This member is required.
71	VerificationAttributes map[string]types.IdentityVerificationAttributes
72
73	// Metadata pertaining to the operation's result.
74	ResultMetadata middleware.Metadata
75}
76
77func addOperationGetIdentityVerificationAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) {
78	err = stack.Serialize.Add(&awsAwsquery_serializeOpGetIdentityVerificationAttributes{}, middleware.After)
79	if err != nil {
80		return err
81	}
82	err = stack.Deserialize.Add(&awsAwsquery_deserializeOpGetIdentityVerificationAttributes{}, middleware.After)
83	if err != nil {
84		return err
85	}
86	if err = addSetLoggerMiddleware(stack, options); err != nil {
87		return err
88	}
89	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
90		return err
91	}
92	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
93		return err
94	}
95	if err = addResolveEndpointMiddleware(stack, options); err != nil {
96		return err
97	}
98	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
99		return err
100	}
101	if err = addRetryMiddlewares(stack, options); err != nil {
102		return err
103	}
104	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
105		return err
106	}
107	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
108		return err
109	}
110	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
111		return err
112	}
113	if err = addClientUserAgent(stack); err != nil {
114		return err
115	}
116	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
117		return err
118	}
119	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
120		return err
121	}
122	if err = addOpGetIdentityVerificationAttributesValidationMiddleware(stack); err != nil {
123		return err
124	}
125	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetIdentityVerificationAttributes(options.Region), middleware.Before); err != nil {
126		return err
127	}
128	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
129		return err
130	}
131	if err = addResponseErrorMiddleware(stack); err != nil {
132		return err
133	}
134	if err = addRequestResponseLogging(stack, options); err != nil {
135		return err
136	}
137	return nil
138}
139
140// GetIdentityVerificationAttributesAPIClient is a client that implements the
141// GetIdentityVerificationAttributes operation.
142type GetIdentityVerificationAttributesAPIClient interface {
143	GetIdentityVerificationAttributes(context.Context, *GetIdentityVerificationAttributesInput, ...func(*Options)) (*GetIdentityVerificationAttributesOutput, error)
144}
145
146var _ GetIdentityVerificationAttributesAPIClient = (*Client)(nil)
147
148// IdentityExistsWaiterOptions are waiter options for IdentityExistsWaiter
149type IdentityExistsWaiterOptions struct {
150
151	// Set of options to modify how an operation is invoked. These apply to all
152	// operations invoked for this client. Use functional options on operation call to
153	// modify this list for per operation behavior.
154	APIOptions []func(*middleware.Stack) error
155
156	// MinDelay is the minimum amount of time to delay between retries. If unset,
157	// IdentityExistsWaiter will use default minimum delay of 3 seconds. Note that
158	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
159	MinDelay time.Duration
160
161	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
162	// to zero, IdentityExistsWaiter will use default max delay of 120 seconds. Note
163	// that MaxDelay must resolve to value greater than or equal to the MinDelay.
164	MaxDelay time.Duration
165
166	// LogWaitAttempts is used to enable logging for waiter retry attempts
167	LogWaitAttempts bool
168
169	// Retryable is function that can be used to override the service defined
170	// waiter-behavior based on operation output, or returned error. This function is
171	// used by the waiter to decide if a state is retryable or a terminal state. By
172	// default service-modeled logic will populate this option. This option can thus be
173	// used to define a custom waiter state with fall-back to service-modeled waiter
174	// state mutators.The function returns an error in case of a failure state. In case
175	// of retry state, this function returns a bool value of true and nil error, while
176	// in case of success it returns a bool value of false and nil error.
177	Retryable func(context.Context, *GetIdentityVerificationAttributesInput, *GetIdentityVerificationAttributesOutput, error) (bool, error)
178}
179
180// IdentityExistsWaiter defines the waiters for IdentityExists
181type IdentityExistsWaiter struct {
182	client GetIdentityVerificationAttributesAPIClient
183
184	options IdentityExistsWaiterOptions
185}
186
187// NewIdentityExistsWaiter constructs a IdentityExistsWaiter.
188func NewIdentityExistsWaiter(client GetIdentityVerificationAttributesAPIClient, optFns ...func(*IdentityExistsWaiterOptions)) *IdentityExistsWaiter {
189	options := IdentityExistsWaiterOptions{}
190	options.MinDelay = 3 * time.Second
191	options.MaxDelay = 120 * time.Second
192	options.Retryable = identityExistsStateRetryable
193
194	for _, fn := range optFns {
195		fn(&options)
196	}
197	return &IdentityExistsWaiter{
198		client:  client,
199		options: options,
200	}
201}
202
203// Wait calls the waiter function for IdentityExists waiter. The maxWaitDur is the
204// maximum wait duration the waiter will wait. The maxWaitDur is required and must
205// be greater than zero.
206func (w *IdentityExistsWaiter) Wait(ctx context.Context, params *GetIdentityVerificationAttributesInput, maxWaitDur time.Duration, optFns ...func(*IdentityExistsWaiterOptions)) error {
207	if maxWaitDur <= 0 {
208		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
209	}
210
211	options := w.options
212	for _, fn := range optFns {
213		fn(&options)
214	}
215
216	if options.MaxDelay <= 0 {
217		options.MaxDelay = 120 * time.Second
218	}
219
220	if options.MinDelay > options.MaxDelay {
221		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
222	}
223
224	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
225	defer cancelFn()
226
227	logger := smithywaiter.Logger{}
228	remainingTime := maxWaitDur
229
230	var attempt int64
231	for {
232
233		attempt++
234		apiOptions := options.APIOptions
235		start := time.Now()
236
237		if options.LogWaitAttempts {
238			logger.Attempt = attempt
239			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
240			apiOptions = append(apiOptions, logger.AddLogger)
241		}
242
243		out, err := w.client.GetIdentityVerificationAttributes(ctx, params, func(o *Options) {
244			o.APIOptions = append(o.APIOptions, apiOptions...)
245		})
246
247		retryable, err := options.Retryable(ctx, params, out, err)
248		if err != nil {
249			return err
250		}
251		if !retryable {
252			return nil
253		}
254
255		remainingTime -= time.Since(start)
256		if remainingTime < options.MinDelay || remainingTime <= 0 {
257			break
258		}
259
260		// compute exponential backoff between waiter retries
261		delay, err := smithywaiter.ComputeDelay(
262			attempt, options.MinDelay, options.MaxDelay, remainingTime,
263		)
264		if err != nil {
265			return fmt.Errorf("error computing waiter delay, %w", err)
266		}
267
268		remainingTime -= delay
269		// sleep for the delay amount before invoking a request
270		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
271			return fmt.Errorf("request cancelled while waiting, %w", err)
272		}
273	}
274	return fmt.Errorf("exceeded max wait time for IdentityExists waiter")
275}
276
277func identityExistsStateRetryable(ctx context.Context, input *GetIdentityVerificationAttributesInput, output *GetIdentityVerificationAttributesOutput, err error) (bool, error) {
278
279	if err == nil {
280		pathValue, err := jmespath.Search("VerificationAttributes.*.VerificationStatus", output)
281		if err != nil {
282			return false, fmt.Errorf("error evaluating waiter state: %w", err)
283		}
284
285		expectedValue := "Success"
286		var match = true
287		listOfValues, ok := pathValue.([]interface{})
288		if !ok {
289			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
290		}
291
292		if len(listOfValues) == 0 {
293			match = false
294		}
295		for _, v := range listOfValues {
296			value, ok := v.(string)
297			if !ok {
298				return false, fmt.Errorf("waiter comparator expected string value, got %T", pathValue)
299			}
300
301			if string(value) != expectedValue {
302				match = false
303			}
304		}
305
306		if match {
307			return false, nil
308		}
309	}
310
311	return true, nil
312}
313
314func newServiceMetadataMiddleware_opGetIdentityVerificationAttributes(region string) *awsmiddleware.RegisterServiceMetadata {
315	return &awsmiddleware.RegisterServiceMetadata{
316		Region:        region,
317		ServiceID:     ServiceID,
318		SigningName:   "ses",
319		OperationName: "GetIdentityVerificationAttributes",
320	}
321}
322